From 373890ffacb7f52e12429b29401e22be76158d9d Mon Sep 17 00:00:00 2001 From: Lucy Date: Wed, 13 Mar 2024 20:20:40 -0400 Subject: [PATCH] Dual 514-515 compat (+ reformatting) (#85) --- .cargo/{config => config.toml} | 0 .rustfmt.toml | 39 +++ Cargo.lock | 2 +- Cargo.toml | 20 +- auxcov/Cargo.toml | 5 +- auxcov/src/codecov.rs | 79 ++--- auxcov/src/lib.rs | 33 +- auxtools-impl/Cargo.toml | 9 +- auxtools-impl/src/lib.rs | 64 ++-- auxtools/Cargo.toml | 11 +- auxtools/src/byond_ffi.rs | 55 ++- auxtools/src/bytecode_manager.rs | 19 +- auxtools/src/debug.rs | 40 +-- auxtools/src/hooks.rs | 59 ++-- auxtools/src/init.rs | 3 +- auxtools/src/lib.rs | 24 +- auxtools/src/list.rs | 40 +-- auxtools/src/proc.rs | 60 ++-- auxtools/src/raw_types/funcs.rs | 43 +-- auxtools/src/raw_types/lists.rs | 6 +- auxtools/src/raw_types/misc.rs | 18 +- auxtools/src/raw_types/procs.rs | 30 +- auxtools/src/raw_types/strings.rs | 2 +- auxtools/src/raw_types/values.rs | 23 +- auxtools/src/raw_types/variables.rs | 2 +- auxtools/src/runtime.rs | 18 +- auxtools/src/sigscan.rs | 32 +- auxtools/src/sigscan/linux.rs | 38 +-- auxtools/src/sigscan/windows.rs | 33 +- auxtools/src/string.rs | 36 +- auxtools/src/string_intern.rs | 8 +- auxtools/src/value.rs | 120 +++---- auxtools/src/value_from.rs | 46 +-- auxtools/src/version.rs | 13 +- auxtools/src/weak_value.rs | 32 +- debug_server/Cargo.toml | 9 +- debug_server/src/assemble_env.rs | 8 +- debug_server/src/ckey_override.rs | 8 +- debug_server/src/crash_handler_windows.rs | 10 +- debug_server/src/instruction_hooking.rs | 83 ++--- debug_server/src/lib.rs | 41 +-- debug_server/src/mem_profiler.rs | 34 +- debug_server/src/server.rs | 322 +++++++----------- debug_server/src/server_types.rs | 64 ++-- debug_server/src/stddef.rs | 9 +- instruction_hooking/Cargo.toml | 5 +- instruction_hooking/build.rs | 9 +- .../514/execute_instruction_hook.windows.S | 20 ++ .../514/execute_instruction_hook.windows.asm | 22 ++ instruction_hooking/src/disassemble_env.rs | 18 +- instruction_hooking/src/lib.rs | 45 ++- tests/auxtest/src/strings.rs | 82 ++--- tests/auxtest/src/value_from.rs | 20 +- tests/auxtest/src/weak.rs | 8 +- tests/byond_get/src/main.rs | 31 +- tests/test_runner/src/main.rs | 24 +- 56 files changed, 828 insertions(+), 1106 deletions(-) rename .cargo/{config => config.toml} (100%) create mode 100644 instruction_hooking/src/514/execute_instruction_hook.windows.S create mode 100644 instruction_hooking/src/514/execute_instruction_hook.windows.asm diff --git a/.cargo/config b/.cargo/config.toml similarity index 100% rename from .cargo/config rename to .cargo/config.toml diff --git a/.rustfmt.toml b/.rustfmt.toml index 218e2032..4cf18463 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1 +1,40 @@ +edition = "2021" hard_tabs = true +fn_params_layout = "Tall" +force_explicit_abi = true +match_block_trailing_comma = false +max_width = 150 +merge_derives = true +newline_style = "Unix" +remove_nested_parens = true +reorder_imports = true +reorder_modules = true +use_field_init_shorthand = true +use_small_heuristics = "Default" +# Unstable formatting options below; remove if you REALLY don't wanna use `cargo +nightly fmt` +unstable_features = true +binop_separator = "Front" +brace_style = "SameLineWhere" +condense_wildcard_suffixes = true +control_brace_style = "AlwaysSameLine" +empty_item_single_line = true +format_code_in_doc_comments = true +format_macro_bodies = true +format_macro_matchers = true +format_strings = true +group_imports = "Preserve" +imports_granularity = "Crate" +imports_indent = "Block" +imports_layout = "Mixed" +indent_style = "Block" +match_arm_blocks = true +normalize_comments = true +overflow_delimited_expr = true +reorder_impl_items = true +space_after_colon = true +space_before_colon = false +spaces_around_ranges = false +trailing_comma = "Never" +trailing_semicolon = true +type_punctuation_density = "Wide" +wrap_comments = true diff --git a/Cargo.lock b/Cargo.lock index 6f83ad7c..997ac2a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -721,7 +721,7 @@ dependencies = [ [[package]] name = "debug_server" -version = "2.3.2" +version = "2.3.3" dependencies = [ "auxtools", "bincode", diff --git a/Cargo.toml b/Cargo.toml index f5e713ed..42050376 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,14 +1,14 @@ [workspace] -members = [ - "auxcov", - "auxtools", - "auxtools-impl", - "debug_server", - "instruction_hooking", - "tests/auxtest", - "tests/byond_get", - "tests/test_runner", -] +members = ["auxcov", "auxtools", "auxtools-impl", "debug_server", "instruction_hooking", "tests/auxtest", "tests/byond_get", "tests/test_runner"] +resolver = "2" + +[workspace.package] +authors = ["Sophie Wallace ", "Lucy "] +edition = "2021" +license = "MIT" +repository = "https://github.com/wilox/auxtools" +rust-version = "1.76" +version = "0.1.0" [profile.release] opt-level = 3 diff --git a/auxcov/Cargo.toml b/auxcov/Cargo.toml index ca1b3bb8..0d201f82 100644 --- a/auxcov/Cargo.toml +++ b/auxcov/Cargo.toml @@ -2,8 +2,11 @@ name = "auxcov" version = "1.0.0" authors = ["Jordan Dominion "] -edition = "2018" publish = false +edition.workspace = true +rust-version.workspace = true +repository.workspace = true +license.workspace = true [lib] crate-type = ["cdylib", "lib"] diff --git a/auxcov/src/codecov.rs b/auxcov/src/codecov.rs index fac8553e..6c0d1b75 100644 --- a/auxcov/src/codecov.rs +++ b/auxcov/src/codecov.rs @@ -1,30 +1,29 @@ -use std::cell::RefCell; -use std::collections::{BTreeMap, HashMap, HashSet}; -use std::convert::TryInto; -use std::fs::create_dir_all; -use std::io::Error; -use std::panic::catch_unwind; -use std::path::{Path, PathBuf}; -use std::rc::Rc; - -use auxtools::raw_types::strings::StringId; -use auxtools::*; +use std::{ + cell::RefCell, + collections::{BTreeMap, HashMap, HashSet}, + convert::TryInto, + fs::create_dir_all, + io::Error, + panic::catch_unwind, + path::{Path, PathBuf}, + rc::Rc +}; + +use auxtools::{raw_types::strings::StringId, *}; use dmasm::Instruction; - use grcov::{output_cobertura, CovResult, FunctionMap, ResultTuple}; -use instruction_hooking::disassemble_env::DisassembleEnv; -use instruction_hooking::InstructionHook; +use instruction_hooking::{disassemble_env::DisassembleEnv, InstructionHook}; struct TrackerContext { output_file_name: String, proc_id_map: Vec>>>>, - filename_map: HashMap>>>, + filename_map: HashMap>>> } pub struct Tracker { hittable_lines: HashMap>, contexts: Vec, - total_procs: u32, + total_procs: u32 } impl Tracker { @@ -51,7 +50,7 @@ impl Tracker { let string_ref_result = StringRef::from_raw(&file.0); match string_ref_result { Ok(string_ref) => current_file_option = Some(string_ref), - Err(_) => current_file_option = None, + Err(_) => current_file_option = None } } Instruction::DbgLine(line) => { @@ -64,10 +63,7 @@ impl Tracker { continue; } - hittable_lines - .entry(file_name) - .or_insert(HashSet::new()) - .insert(line); + hittable_lines.entry(file_name).or_insert(HashSet::new()).insert(line); } } _ => {} @@ -79,23 +75,19 @@ impl Tracker { Tracker { hittable_lines, contexts: Vec::new(), - total_procs: i, + total_procs: i } } pub fn init_context(&mut self, output_file_name: String) -> bool { - if self - .contexts - .iter() - .any(|context| context.output_file_name == *output_file_name) - { + if self.contexts.iter().any(|context| context.output_file_name == *output_file_name) { return false; } let mut context: TrackerContext = TrackerContext { output_file_name, proc_id_map: Vec::new(), - filename_map: HashMap::new(), + filename_map: HashMap::new() }; context.proc_id_map.reserve(self.total_procs as usize); @@ -126,11 +118,7 @@ impl Tracker { } // returns true if we need to pause - pub fn process_dbg_line( - &mut self, - ctx: &raw_types::procs::ExecutionContext, - proc_instance: &raw_types::procs::ProcInstance, - ) { + pub fn process_dbg_line(&mut self, ctx: &raw_types::procs::ExecutionContext, proc_instance: &raw_types::procs::ProcInstance) { if ctx.line == 0 || !ctx.filename.valid() { return; } @@ -146,8 +134,7 @@ impl Tracker { context.process_dbg_line(filename_id, proc_map_index, line, Some(file_name)); } None => { - let processed_file_name = - context.process_dbg_line(filename_id, proc_map_index, line, None); + let processed_file_name = context.process_dbg_line(filename_id, proc_map_index, line, None); if let Some((file_name, valid)) = processed_file_name { if !valid { break; @@ -213,7 +200,8 @@ impl Tracker { impl Drop for Tracker { fn drop(&mut self) { - let _result = self.finalize(); // dropping the result here because what can ya do? + let _result = self.finalize(); // dropping the result here because what can ya + // do? } } @@ -236,7 +224,7 @@ impl TrackerContext { filename_id: StringId, proc_map_index: usize, line: usize, - known_file_name: Option<&String>, + known_file_name: Option<&String> ) -> Option<(String, bool)> { let needs_extending = self.proc_id_map.len() < proc_map_index + 1; @@ -324,8 +312,7 @@ impl TrackerContext { hit_map[i] = current_hits + 1; let hit_map_rc = Rc::new(RefCell::new(hit_map)); - self.filename_map - .insert(file_name.clone(), hit_map_rc.clone()); + self.filename_map.insert(file_name.clone(), hit_map_rc.clone()); self.proc_id_map[proc_map_index] = Some(hit_map_rc); } } @@ -348,15 +335,11 @@ impl TrackerContext { } let path = PathBuf::from(file_name); - ( - path.clone(), - path, - CovResult { - lines: new_map, - branches: BTreeMap::default(), - functions: FunctionMap::default(), - }, - ) + (path.clone(), path, CovResult { + lines: new_map, + branches: BTreeMap::default(), + functions: FunctionMap::default() + }) }) .collect(); diff --git a/auxcov/src/lib.rs b/auxcov/src/lib.rs index 26ca9415..4234fd65 100644 --- a/auxcov/src/lib.rs +++ b/auxcov/src/lib.rs @@ -2,24 +2,21 @@ mod codecov; -use codecov::Tracker; -use instruction_hooking::INSTRUCTION_HOOKS; - use std::any::{Any, TypeId}; use auxtools::*; +use codecov::Tracker; +use instruction_hooking::INSTRUCTION_HOOKS; fn with_tracker_option(f: F, create: bool) where - F: FnOnce(&mut Tracker), + F: FnOnce(&mut Tracker) { unsafe { let hooks = INSTRUCTION_HOOKS.get_mut(); let tracker_tid = TypeId::of::(); - let tracker_option = hooks - .iter_mut() - .find(|hook| (*hook).as_ref().type_id() == tracker_tid); + let tracker_option = hooks.iter_mut().find(|hook| (*hook).as_ref().type_id() == tracker_tid); match tracker_option { Some(existing_hook) => { @@ -39,7 +36,8 @@ where } } -// INSTRUCTION_HOOKS are cleared on shutdown so we don't need to worry about that. +// INSTRUCTION_HOOKS are cleared on shutdown so we don't need to worry about +// that. #[hook("/proc/start_code_coverage")] fn start_code_coverage(coverage_file: Value) { let coverage_file_string_result = coverage_file.as_string(); @@ -54,14 +52,11 @@ fn start_code_coverage(coverage_file: Value) { |tracker| { init_result = tracker.init_context(coverage_file_string.clone()); }, - true, + true ); if !init_result { - return Err(runtime!( - "A code coverage context for {} already exists!", - coverage_file_string - )); + return Err(runtime!("A code coverage context for {} already exists!", coverage_file_string)); } Ok(Value::null()) @@ -83,21 +78,15 @@ fn stop_code_coverage(coverage_file: Value) { result = match inner_result { Ok(had_entry) => { if !had_entry { - Err(runtime!( - "A code coverage context for {} does not exist!", - coverage_file_string - )) + Err(runtime!("A code coverage context for {} does not exist!", coverage_file_string)) } else { Ok(Value::null()) } } - Err(error) => Err(runtime!( - "A error occurred while trying to save the coverage file: {}", - error - )), + Err(error) => Err(runtime!("A error occurred while trying to save the coverage file: {}", error)) } }, - false, + false ); result diff --git a/auxtools-impl/Cargo.toml b/auxtools-impl/Cargo.toml index 80996bf4..da466901 100644 --- a/auxtools-impl/Cargo.toml +++ b/auxtools-impl/Cargo.toml @@ -2,10 +2,11 @@ name = "auxtools-impl" description = "procedural macros for use with the auxtools crate" version = "0.1.0" -authors = ["Aspen ", "Sophie Wallace "] -license = "MIT" -repository = "https://github.com/willox/auxtools" -edition = "2018" +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +repository.workspace = true +license.workspace = true [lib] proc-macro = true diff --git a/auxtools-impl/src/lib.rs b/auxtools-impl/src/lib.rs index f9f1e4f1..adcf03df 100644 --- a/auxtools-impl/src/lib.rs +++ b/auxtools-impl/src/lib.rs @@ -17,7 +17,7 @@ fn from_signature(s: String) -> Vec> { hex::decode(byte).map(|decoded_byte| decoded_byte[0]).ok() } } - _ => None, + _ => None } }) .collect() @@ -28,7 +28,7 @@ pub fn convert_signature(input: TokenStream) -> TokenStream { let string = parse_macro_input!(input as Lit); let string = match string { Lit::Str(lit) => lit.value(), - _ => panic!("not string input"), + _ => panic!("not string input") }; let streams: Vec = from_signature(string) @@ -54,7 +54,7 @@ pub fn convert_signature(input: TokenStream) -> TokenStream { fn extract_args(a: &syn::FnArg) -> &syn::PatType { match a { syn::FnArg::Typed(p) => p, - _ => panic!("Not supported on types with `self`!"), + _ => panic!("Not supported on types with `self`!") } } @@ -67,11 +67,7 @@ pub fn init(attr: TokenStream, item: TokenStream) -> TokenStream { let func_type = match init_type.to_string().as_str() { "full" => quote! { auxtools::FullInitFunc }, "partial" => quote! { auxtools::PartialInitFunc }, - _ => { - return syn::Error::new(init_type.span(), "invalid init type") - .to_compile_error() - .into() - } + _ => return syn::Error::new(init_type.span(), "invalid init type").to_compile_error().into() }; let inventory_define = quote! { @@ -148,17 +144,19 @@ pub fn full_shutdown(_: TokenStream, item: TokenStream) -> TokenStream { /// The `pin_dll!` macro is used to determine whether the dll handle auxtools /// takes on Windows is pinned. For reference, a dll with a pinned handle cannot -/// be unloaded during execution of the host process - termination of the host is -/// the only way to unload the dll and release the lock on the corresponding file. +/// be unloaded during execution of the host process - termination of the host +/// is the only way to unload the dll and release the lock on the corresponding +/// file. /// -/// This has very limited use cases - for instance, if a .dmb is hosted on a live -/// server whose Dream Daemon process is kept running between runs, keeping a pinned -/// handle to the dll will prevent the corresponding file from being updated by -/// automatic updaters such as tgs. You shouldn't use this unless you very specifically -/// need it for your particular use case. +/// This has very limited use cases - for instance, if a .dmb is hosted on a +/// live server whose Dream Daemon process is kept running between runs, keeping +/// a pinned handle to the dll will prevent the corresponding file from being +/// updated by automatic updaters such as tgs. You shouldn't use this unless you +/// very specifically need it for your particular use case. /// -/// Libraries that unpin the dll using this macro should ensure that no spawned threads -/// are running when calling `auxtools_full_shutdown` from DM, or else Dream Daemon will crash. +/// Libraries that unpin the dll using this macro should ensure that no spawned +/// threads are running when calling `auxtools_full_shutdown` from DM, or else +/// Dream Daemon will crash. #[proc_macro] pub fn pin_dll(attr: TokenStream) -> TokenStream { let flag = syn::parse_macro_input!(attr as syn::LitBool); @@ -175,14 +173,14 @@ pub fn pin_dll(attr: TokenStream) -> TokenStream { code.into() } -/// The `hook` attribute is used to define functions that may be used as proc hooks, -/// and to optionally hook those procs upon library initialization. +/// The `hook` attribute is used to define functions that may be used as proc +/// hooks, and to optionally hook those procs upon library initialization. /// /// # Examples /// /// Here we define a hook that multiplies a number passed to it by two. -/// It can now be used to hook procs, for example `hooks::hook("/proc/double_up", double_up);` -/// ```ignore +/// It can now be used to hook procs, for example +/// `hooks::hook("/proc/double_up", double_up);` ```ignore /// #[hook] /// fn double_up(num: Value) { /// if let Some(num) = num.as_number() { @@ -191,10 +189,9 @@ pub fn pin_dll(attr: TokenStream) -> TokenStream { /// Value::null() /// } /// ``` -/// +/// /// This function is used to hook `/mob/proc/on_honked`. /// By specifying the proc path, we hook the proc immediately upon startup. -/// /// ```ignore /// #[hook("/mob/proc/on_honked")] /// fn on_honked(honker: Value) { @@ -231,14 +228,11 @@ pub fn hook(attr: TokenStream, item: TokenStream) -> TokenStream { } } Some(other_literal) => { - return syn::Error::new( - other_literal.span(), - "Hook attributes must be a string literal", - ) - .to_compile_error() - .into() + return syn::Error::new(other_literal.span(), "Hook attributes must be a string literal") + .to_compile_error() + .into() } - None => quote! {}, + None => quote! {} }; let signature = quote! { fn #func_name( @@ -249,12 +243,8 @@ pub fn hook(attr: TokenStream, item: TokenStream) -> TokenStream { }; let body = &input.block; - let mut arg_names: syn::punctuated::Punctuated = - syn::punctuated::Punctuated::new(); - let mut proc_arg_unpacker: syn::punctuated::Punctuated< - proc_macro2::TokenStream, - syn::Token![,], - > = syn::punctuated::Punctuated::new(); + let mut arg_names: syn::punctuated::Punctuated = syn::punctuated::Punctuated::new(); + let mut proc_arg_unpacker: syn::punctuated::Punctuated = syn::punctuated::Punctuated::new(); for arg in args.iter().map(extract_args) { if let syn::Pat::Ident(p) = &*arg.pat { @@ -264,7 +254,7 @@ pub fn hook(attr: TokenStream, item: TokenStream) -> TokenStream { (quote! { &args[#index] }) - .into(), + .into() ); } } diff --git a/auxtools/Cargo.toml b/auxtools/Cargo.toml index e506fe88..43ceaa23 100644 --- a/auxtools/Cargo.toml +++ b/auxtools/Cargo.toml @@ -1,11 +1,12 @@ [package] name = "auxtools" description = "library for interfacing with low-level BYOND internals" -version = "0.1.0" -authors = ["Sophie Wallace "] -license = "MIT" -repository = "https://github.com/willox/auxtools" -edition = "2018" +version.workspace = true +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +repository.workspace = true +license.workspace = true [build-dependencies] cc = "1.0" diff --git a/auxtools/src/byond_ffi.rs b/auxtools/src/byond_ffi.rs index d6aa0149..0de440c0 100644 --- a/auxtools/src/byond_ffi.rs +++ b/auxtools/src/byond_ffi.rs @@ -1,35 +1,33 @@ -/* - https://github.com/tgstation/rust-g/tree/2e9b7724ba81894863d77fd1d27a2e24b79d67bf - - MIT License - - Copyright (c) 2018 Bjorn Neergaard, /tg/station contributors - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ +// https://github.com/tgstation/rust-g/tree/2e9b7724ba81894863d77fd1d27a2e24b79d67bf +// +// MIT License +// +// Copyright (c) 2018 Bjorn Neergaard, /tg/station contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. use std::{ borrow::Cow, cell::RefCell, ffi::{CStr, CString}, os::raw::{c_char, c_int}, - slice, + slice }; static EMPTY_STRING: c_char = 0; @@ -62,13 +60,14 @@ pub fn byond_return(value: Option>) -> *const c_char { }; cell.replace(cstring); cell.borrow().as_ptr() - }), + }) } } /// Creates a normal byond ffi function that can be called in DM with [call](http://www.byond.com/docs/ref/#/proc/call). /// -/// You should favour [hooks](attr.hook.html) over these when working with auxtools. +/// You should favour [hooks](attr.hook.html) over these when working with +/// auxtools. /// /// # Examples /// ```ignore diff --git a/auxtools/src/bytecode_manager.rs b/auxtools/src/bytecode_manager.rs index 483369ed..a55dc725 100644 --- a/auxtools/src/bytecode_manager.rs +++ b/auxtools/src/bytecode_manager.rs @@ -1,20 +1,23 @@ -// This module is in control of allocating buffers for use when replacing a proc's bytecode. -// To keep things sane, we also have to return the pointers to their original value before BYOND shuts down. -// We _also_ have to check if any existing procs are still using our bytecode when we shut down and leak the memory if so. -// It may be possible to avoid the leaks but it really doesn't matter. +// This module is in control of allocating buffers for use when replacing a +// proc's bytecode. To keep things sane, we also have to return the pointers to +// their original value before BYOND shuts down. We _also_ have to check if any +// existing procs are still using our bytecode when we shut down and leak the +// memory if so. It may be possible to avoid the leaks but it really doesn't +// matter. -use crate::{debug, raw_types, *}; -use std::convert::TryFrom; use std::{ cell::UnsafeCell, collections::{HashMap, HashSet}, + convert::TryFrom }; +use crate::{debug, raw_types, *}; + static mut BYTECODE_ALLOCATIONS: UnsafeCell> = UnsafeCell::new(None); struct State { allocations: HashSet>, - original: HashMap, + original: HashMap } pub fn init() { @@ -22,7 +25,7 @@ pub fn init() { let ptr = BYTECODE_ALLOCATIONS.get(); *ptr = Some(State { allocations: HashSet::new(), - original: HashMap::new(), + original: HashMap::new() }); } } diff --git a/auxtools/src/debug.rs b/auxtools/src/debug.rs index cc41973d..0269416a 100644 --- a/auxtools/src/debug.rs +++ b/auxtools/src/debug.rs @@ -1,7 +1,7 @@ -use crate::raw_types::{funcs, procs}; -use crate::Proc; -use crate::StringRef; -use crate::Value; +use crate::{ + raw_types::{funcs, procs}, + Proc, StringRef, Value +}; pub struct StackFrame { pub context: *mut procs::ExecutionContext, @@ -14,14 +14,13 @@ pub struct StackFrame { pub args: Vec<(Option, Value)>, pub locals: Vec<(StringRef, Value)>, pub file_name: Option, - pub line_number: Option, - // pub time_to_resume: Option, - // TODO: current instruction & bytecode offset + pub line_number: Option /* pub time_to_resume: Option, + * TODO: current instruction & bytecode offset */ } pub struct CallStacks { pub active: Vec, - pub suspended: Vec>, + pub suspended: Vec> } impl StackFrame { @@ -37,12 +36,13 @@ impl StackFrame { let src = Value::from_raw((*instance).src); let dot = Value::from_raw((*context).dot); - // Make sure to handle arguments/locals with no names (when there are more values than names) + // Make sure to handle arguments/locals with no names (when there are more + // values than names) let args = (0..(*instance).args_count) .map(|i| { let name = match param_names.get(i as usize) { Some(name) => Some(name.clone()), - None => None, + None => None }; (name, Value::from_raw(*((*instance).args).add(i as usize))) }) @@ -52,7 +52,7 @@ impl StackFrame { .map(|i| { ( local_names.get(i as usize).unwrap().clone(), - Value::from_raw(*((*context).locals).add(i as usize)), + Value::from_raw(*((*context).locals).add(i as usize)) ) }) .collect(); @@ -79,15 +79,14 @@ impl StackFrame { args, locals, file_name, - line_number, - // time_to_resume, + line_number // time_to_resume, } } } enum CallStackKind { Active, - Suspended, + Suspended } impl CallStacks { @@ -108,17 +107,12 @@ impl CallStacks { } CallStacks { - active: unsafe { - CallStacks::from_context(*funcs::CURRENT_EXECUTION_CONTEXT, CallStackKind::Active) - }, - suspended, + active: unsafe { CallStacks::from_context(*funcs::CURRENT_EXECUTION_CONTEXT, CallStackKind::Active) }, + suspended } } - fn from_context( - mut context: *mut procs::ExecutionContext, - kind: CallStackKind, - ) -> Vec { + fn from_context(mut context: *mut procs::ExecutionContext, kind: CallStackKind) -> Vec { let mut frames = vec![]; loop { @@ -135,7 +129,7 @@ impl CallStacks { // BYOND stores sleeping stacks' frames in reverse-order match kind { CallStackKind::Active => frames, - CallStackKind::Suspended => frames.into_iter().rev().collect(), + CallStackKind::Suspended => frames.into_iter().rev().collect() } } } diff --git a/auxtools/src/hooks.rs b/auxtools/src/hooks.rs index 8436eb4d..7d6d84a6 100644 --- a/auxtools/src/hooks.rs +++ b/auxtools/src/hooks.rs @@ -1,17 +1,19 @@ -use super::proc::Proc; -use super::raw_types; -use super::value::Value; -use crate::runtime::DMResult; +use std::{ + cell::RefCell, + ffi::{c_void, CStr}, + os::raw::c_char +}; + use detour::RawDetour; use fxhash::FxHashMap; -use std::ffi::c_void; -use std::os::raw::c_char; -use std::{cell::RefCell, ffi::CStr}; + +use super::{proc::Proc, raw_types, value::Value}; +use crate::runtime::DMResult; #[doc(hidden)] pub struct CompileTimeHook { pub proc_path: &'static str, - pub hook: ProcHook, + pub hook: ProcHook } inventory::collect!(CompileTimeHook); @@ -35,20 +37,20 @@ extern "C" { args: *mut raw_types::values::Value, args_count_l: usize, unk_1: u32, - unk_2: u32, + unk_2: u32 ) -> raw_types::values::Value; } struct Detours { pub runtime_detour: Option, - pub call_proc_detour: Option, + pub call_proc_detour: Option } impl Detours { pub fn new() -> Self { Self { runtime_detour: None, - call_proc_detour: None, + call_proc_detour: None } } } @@ -59,7 +61,7 @@ pub enum HookFailure { NotInitialized, ProcNotFound, AlreadyHooked, - UnknownFailure, + UnknownFailure } impl std::fmt::Debug for HookFailure { @@ -68,25 +70,21 @@ impl std::fmt::Debug for HookFailure { Self::NotInitialized => write!(f, "Library not initialized"), Self::ProcNotFound => write!(f, "Proc not found"), Self::AlreadyHooked => write!(f, "Proc is already hooked"), - Self::UnknownFailure => write!(f, "Unknown failure"), + Self::UnknownFailure => write!(f, "Unknown failure") } } } pub fn init() -> Result<(), String> { unsafe { - let runtime_hook = RawDetour::new( - raw_types::funcs::runtime_byond as *const (), - runtime_hook as *const (), - ) - .unwrap(); + let runtime_hook = RawDetour::new(raw_types::funcs::runtime_byond as *const (), runtime_hook as *const ()).unwrap(); runtime_hook.enable().unwrap(); runtime_original = std::mem::transmute(runtime_hook.trampoline()); let call_hook = RawDetour::new( raw_types::funcs::call_proc_by_id_byond as *const (), - call_proc_by_id_hook_trampoline as *const (), + call_proc_by_id_hook_trampoline as *const () ) .unwrap(); @@ -120,11 +118,7 @@ thread_local! { static PROC_HOOKS: RefCell> = RefCell::new(FxHashMap::default()); } -fn hook_by_id( - id: raw_types::procs::ProcId, - hook: ProcHook, - hook_path: String, -) -> Result<(), HookFailure> { +fn hook_by_id(id: raw_types::procs::ProcId, hook: ProcHook, hook_path: String) -> Result<(), HookFailure> { PROC_HOOKS.with(|h| { let mut map = h.borrow_mut(); if map.contains_key(&id) { @@ -143,7 +137,7 @@ pub fn clear_hooks() { pub fn hook>(name: S, hook: ProcHook) -> Result<(), HookFailure> { match super::proc::get_proc(name) { Some(p) => hook_by_id(p.id, hook, p.path.to_owned()), - None => Err(HookFailure::ProcNotFound), + None => Err(HookFailure::ProcNotFound) } } @@ -173,7 +167,7 @@ extern "C" fn call_proc_by_id_hook( args_ptr: *mut raw_types::values::Value, num_args: usize, _unknown2: u32, - _unknown3: u32, + _unknown3: u32 ) -> u8 { match PROC_HOOKS.with(|h| match h.borrow().get(&proc_id) { Some((hook, path)) => { @@ -185,7 +179,7 @@ extern "C" fn call_proc_by_id_hook( std::slice::from_raw_parts(args_ptr, num_args) .iter() .map(|v| Value::from_raw_owned(*v)) - .collect(), + .collect() ) }; @@ -201,18 +195,13 @@ extern "C" fn call_proc_by_id_hook( Err(e) => { Proc::find("/proc/auxtools_stack_trace") .unwrap() - .call(&[&Value::from_string(format!( - "{} HookPath: {}", - e.message.as_str(), - path.as_str() - )) - .unwrap()]) + .call(&[&Value::from_string(format!("{} HookPath: {}", e.message.as_str(), path.as_str())).unwrap()]) .unwrap(); Some(Value::null().raw) } } } - None => None, + None => None }) { Some(result) => { unsafe { @@ -220,6 +209,6 @@ extern "C" fn call_proc_by_id_hook( } 1 } - None => 0, + None => 0 } } diff --git a/auxtools/src/init.rs b/auxtools/src/init.rs index 5925c894..d80981de 100644 --- a/auxtools/src/init.rs +++ b/auxtools/src/init.rs @@ -4,7 +4,7 @@ use crate::inventory; pub enum InitLevel { Full, Partial, - None, + None } pub static mut REQUIRED_INIT: InitLevel = InitLevel::Full; @@ -17,7 +17,6 @@ pub fn set_init_level(level: InitLevel) { unsafe { REQUIRED_INIT = level } } -// // Hooks that run on intiailization // pub type InitFunc = fn() -> Result<(), String>; diff --git a/auxtools/src/lib.rs b/auxtools/src/lib.rs index 474ce07d..f7f34672 100644 --- a/auxtools/src/lib.rs +++ b/auxtools/src/lib.rs @@ -3,7 +3,7 @@ //! For when BYOND is not enough. Probably often. //#[cfg(not(target_pointer_width = "32"))] -//compile_error!("Auxtools must be compiled for a 32-bit target"); +// compile_error!("Auxtools must be compiled for a 32-bit target"); mod byond_ffi; mod bytecode_manager; @@ -22,12 +22,16 @@ mod value_from; pub mod version; mod weak_value; -use init::{get_init_level, set_init_level, InitLevel}; +use std::{ + ffi::c_void, + sync::atomic::{AtomicBool, Ordering} +}; pub use auxtools_impl::{full_shutdown, hook, init, pin_dll, runtime_handler, shutdown}; /// Used by the [pin_dll] macro to set dll pinning pub use ctor; pub use hooks::{CompileTimeHook, RuntimeErrorHook}; +use init::{get_init_level, set_init_level, InitLevel}; pub use init::{FullInitFunc, FullShutdownFunc, PartialInitFunc, PartialShutdownFunc}; /// Used by the [hook](attr.hook.html) macro to aggregate all compile-time hooks pub use inventory; @@ -35,14 +39,13 @@ pub use list::List; pub use proc::Proc; pub use raw_types::variables::VariableNameIdTable; pub use runtime::{DMResult, Runtime}; -use std::ffi::c_void; -use std::sync::atomic::{AtomicBool, Ordering}; pub use string::StringRef; pub use string_intern::InternedString; pub use value::Value; pub use weak_value::WeakValue; -// We need winapi to call GetModuleHandleExW which lets us prevent our DLL from unloading. +// We need winapi to call GetModuleHandleExW which lets us prevent our DLL from +// unloading. #[cfg(windows)] extern crate winapi; @@ -194,20 +197,17 @@ signatures! { } pub static PIN_DLL: AtomicBool = AtomicBool::new(true); -// This strange section of code retrieves our DLL using the init function's address. -// This increments the DLL reference count, which prevents unloading. +// This strange section of code retrieves our DLL using the init function's +// address. This increments the DLL reference count, which prevents unloading. #[cfg(windows)] fn pin_dll() -> Result<(), ()> { unsafe { - use winapi::um::libloaderapi::{ - GetModuleHandleExW, GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, - GET_MODULE_HANDLE_EX_FLAG_PIN, - }; + use winapi::um::libloaderapi::{GetModuleHandleExW, GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, GET_MODULE_HANDLE_EX_FLAG_PIN}; let mut module = std::ptr::null_mut(); let flags = match PIN_DLL.load(Ordering::Relaxed) { true => GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_PIN, - false => GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + false => GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS }; let res = GetModuleHandleExW(flags, pin_dll as *const _, &mut module); diff --git a/auxtools/src/list.rs b/auxtools/src/list.rs index f1262dbc..9a069fcc 100644 --- a/auxtools/src/list.rs +++ b/auxtools/src/list.rs @@ -1,9 +1,11 @@ -use crate::*; use std::iter::FromIterator; -/// A wrapper around [Values](struct.Value.html) that make working with lists a little easier +use crate::*; + +/// A wrapper around [Values](struct.Value.html) that make working with lists a +/// little easier pub struct List { - value: Value, + value: Value } impl List { @@ -29,10 +31,10 @@ impl List { let raw = raw_types::values::Value { tag: raw_types::values::ValueTag::List, - data: raw_types::values::ValueData { id: id.0 }, + data: raw_types::values::ValueData { id: id.0 } }; Self { - value: unsafe { Value::from_raw_owned(raw) }, + value: unsafe { Value::from_raw_owned(raw) } } } @@ -41,7 +43,7 @@ impl List { let mut value = raw_types::values::Value { tag: raw_types::values::ValueTag::Null, - data: raw_types::values::ValueData { id: 0 }, + data: raw_types::values::ValueData { id: 0 } }; // assoc funcs for everything else @@ -50,17 +52,11 @@ impl List { return Ok(Value::from_raw_owned(value)); } - Err(runtime!( - "failed to get assoc list entry (probably given an invalid list or key)" - )) + Err(runtime!("failed to get assoc list entry (probably given an invalid list or key)")) } } - pub fn set, V: Into>( - &self, - index: K, - value: V, - ) -> Result<(), runtime::Runtime> { + pub fn set, V: Into>(&self, index: K, value: V) -> Result<(), runtime::Runtime> { let index = index.into(); let value = value.into(); @@ -69,9 +65,7 @@ impl List { return Ok(()); } - Err(runtime!( - "failed to set assoc list entry (probably given an invalid list or key)" - )) + Err(runtime!("failed to set assoc list entry (probably given an invalid list or key)")) } } @@ -79,10 +73,7 @@ impl List { let value = value.into(); unsafe { - assert_eq!( - raw_types::funcs::append_to_list(self.value.raw, value.raw), - 1 - ); + assert_eq!(raw_types::funcs::append_to_list(self.value.raw, value.raw), 1); } } @@ -90,10 +81,7 @@ impl List { let value = value.into(); unsafe { - assert_eq!( - raw_types::funcs::remove_from_list(self.value.raw, value.raw), - 1 - ); + assert_eq!(raw_types::funcs::remove_from_list(self.value.raw, value.raw), 1); } } @@ -140,7 +128,7 @@ impl List { | raw_types::values::ValueTag::MobVisLocs | raw_types::values::ValueTag::WorldVars | raw_types::values::ValueTag::GlobalVars => true, - _ => false, + _ => false } } } diff --git a/auxtools/src/proc.rs b/auxtools/src/proc.rs index 7ecfaab1..29864d40 100644 --- a/auxtools/src/proc.rs +++ b/auxtools/src/proc.rs @@ -1,39 +1,40 @@ -use crate::*; +use std::{ + cell::RefCell, + collections::{hash_map::Entry, HashMap}, + fmt +}; + use ahash::RandomState; use fxhash::FxHashMap; -use std::cell::RefCell; -use std::collections::{hash_map::Entry, HashMap}; -use std::fmt; -// +use crate::*; + // ### A note on Override IDs // // Procs in DM can be defined multiple times. // // ``` // /proc/hello() // Override #0 or base proc -// world << "Hello" +// world << "Hello" // -// /hello() // Override #1 -// ..() // Calls override #0 -// world << "World" +// /hello() // Override #1 +// ..() // Calls override #0 +// world << "World" // -// /hello() // Override #2 -// ..() // Calls override #1 -// world << "!!!" -// ``` +// /hello() // Override #2 +// ..() // Calls override #1 +// world << "!!!" +// ``` // -// To get the nth override, use [get_proc_override]: `let hello = get_proc_override("/proc/hello", n).unwrap()` +// To get the nth override, use [get_proc_override]: `let hello = get_proc_override("/proc/hello", n).unwrap()` // [get_proc] retrieves the base proc. -// -// /// Used to hook and call procs. #[derive(Clone)] pub struct Proc { pub id: raw_types::procs::ProcId, pub entry: *mut raw_types::procs::ProcEntry, - pub path: String, + pub path: String } impl Proc { @@ -50,19 +51,16 @@ impl Proc { pub fn from_id(id: raw_types::procs::ProcId) -> Option { let mut proc_entry: *mut raw_types::procs::ProcEntry = std::ptr::null_mut(); unsafe { - assert_eq!( - raw_types::funcs::get_proc_array_entry(&mut proc_entry, id), - 1 - ); + assert_eq!(raw_types::funcs::get_proc_array_entry(&mut proc_entry, id), 1); } if proc_entry.is_null() { return None; } let proc_name = strip_path(unsafe { StringRef::from_id((*proc_entry).path).into() }); Some(Proc { - id: id, + id, entry: proc_entry, - path: proc_name.clone(), + path: proc_name.clone() }) } @@ -83,18 +81,14 @@ impl Proc { pub fn parameter_names(&self) -> Vec { unsafe { let (data, count) = raw_types::misc::get_parameters((*self.entry).metadata.get_parameters()); - (0..count) - .map(|i| StringRef::from_variable_id((*data.add(i as usize)).name)) - .collect() + (0..count).map(|i| StringRef::from_variable_id((*data.add(i as usize)).name)).collect() } } pub fn local_names(&self) -> Vec { unsafe { let (names, count) = raw_types::misc::get_locals((*self.entry).metadata.get_locals()); - (0..count) - .map(|i| StringRef::from_variable_id(*names.add(i as usize))) - .collect() + (0..count).map(|i| StringRef::from_variable_id(*names.add(i as usize))).collect() } } @@ -126,7 +120,7 @@ impl Proc { pub fn call(&self, args: &[&Value]) -> runtime::DMResult { let mut ret = raw_types::values::Value { tag: raw_types::values::ValueTag::Null, - data: raw_types::values::ValueData { id: 0 }, + data: raw_types::values::ValueData { id: 0 } }; unsafe { @@ -147,7 +141,7 @@ impl Proc { args.as_ptr(), args.len(), 0, - 0, + 0 ) == 1 { return Ok(Value::from_raw_owned(ret)); @@ -160,7 +154,7 @@ impl Proc { pub fn override_id(&self) -> u32 { PROC_OVERRIDE_IDS.with(|override_ids| match override_ids.borrow().get(&self.id) { Some(id) => *id, - None => 0, + None => 0 }) } } @@ -219,7 +213,7 @@ pub fn get_proc_override>(path: S, override_id: u32) -> Option

Some(p.clone()), - None => None, + None => None }) } diff --git a/auxtools/src/raw_types/funcs.rs b/auxtools/src/raw_types/funcs.rs index a4f0d657..6f1d58e5 100644 --- a/auxtools/src/raw_types/funcs.rs +++ b/auxtools/src/raw_types/funcs.rs @@ -1,12 +1,6 @@ -use super::lists; -use super::misc; -use super::procs; -use super::strings; -use super::values; -use super::variables; +use std::{ffi::c_void, os::raw::c_char}; -use std::ffi::c_void; -use std::os::raw::c_char; +use super::{lists, misc, procs, strings, values, variables}; // TODO: Doesn't belong here at all pub static mut CURRENT_EXECUTION_CONTEXT: *mut *mut procs::ExecutionContext = std::ptr::null_mut(); @@ -16,7 +10,8 @@ pub static mut SUSPENDED_PROCS: *mut procs::SuspendedProcs = std::ptr::null_mut( pub static mut VARIABLE_NAMES: *const variables::VariableNameIdTable = std::ptr::null(); // Function pointers exported by C++ but set by Rust -// Rust shouldn't call these so we're going to treat them as void ptrs for simplicity +// Rust shouldn't call these so we're going to treat them as void ptrs for +// simplicity extern "C" { pub static mut call_proc_by_id_byond: *const c_void; pub static mut call_datum_proc_by_name_byond: *const c_void; @@ -50,7 +45,7 @@ extern "C" { args: *const values::Value, args_count_l: usize, unk_1: u32, - unk_2: u32, + unk_2: u32 ) -> u8; pub fn call_datum_proc_by_name( out: *mut values::Value, @@ -61,33 +56,17 @@ extern "C" { args: *mut values::Value, args_count_l: usize, unk_0: u32, - unk_1: u32, + unk_1: u32 ) -> u8; pub fn get_proc_array_entry(out: *mut *mut procs::ProcEntry, id: procs::ProcId) -> u8; pub fn get_string_id(out: *mut strings::StringId, string: *const c_char) -> u8; - pub fn get_variable( - out: *mut values::Value, - datum: values::Value, - index: strings::StringId, - ) -> u8; - pub fn set_variable(datum: values::Value, index: strings::StringId, value: values::Value) - -> u8; - pub fn get_string_table_entry( - out: *mut *mut strings::StringEntry, - index: strings::StringId, - ) -> u8; + pub fn get_variable(out: *mut values::Value, datum: values::Value, index: strings::StringId) -> u8; + pub fn set_variable(datum: values::Value, index: strings::StringId, value: values::Value) -> u8; + pub fn get_string_table_entry(out: *mut *mut strings::StringEntry, index: strings::StringId) -> u8; pub fn inc_ref_count(value: values::Value) -> u8; pub fn dec_ref_count(value: values::Value) -> u8; - pub fn get_assoc_element( - out: *mut values::Value, - datum: values::Value, - index: values::Value, - ) -> u8; - pub fn set_assoc_element( - datum: values::Value, - index: values::Value, - value: values::Value, - ) -> u8; + pub fn get_assoc_element(out: *mut values::Value, datum: values::Value, index: values::Value) -> u8; + pub fn set_assoc_element(datum: values::Value, index: values::Value, value: values::Value) -> u8; pub fn create_list(out: *mut lists::ListId, reserve_capacity: u32) -> u8; pub fn append_to_list(list: values::Value, value: values::Value) -> u8; pub fn remove_from_list(list: values::Value, value: values::Value) -> u8; diff --git a/auxtools/src/raw_types/lists.rs b/auxtools/src/raw_types/lists.rs index d2cfa80f..38b0c875 100644 --- a/auxtools/src/raw_types/lists.rs +++ b/auxtools/src/raw_types/lists.rs @@ -8,7 +8,7 @@ pub struct ListId(pub u32); #[allow(unused)] enum Color { Red = 0, - Black = 1, + Black = 1 } #[repr(C)] @@ -17,7 +17,7 @@ pub struct AssociativeListEntry { value: values::Value, color: Color, left: *mut AssociativeListEntry, - right: *mut AssociativeListEntry, + right: *mut AssociativeListEntry } #[repr(C)] @@ -27,5 +27,5 @@ pub struct List { pub allocated: u32, pub length: u32, pub refcount: u32, - unknown: u32, + unknown: u32 } diff --git a/auxtools/src/raw_types/misc.rs b/auxtools/src/raw_types/misc.rs index 332cbeaf..21d0edce 100644 --- a/auxtools/src/raw_types/misc.rs +++ b/auxtools/src/raw_types/misc.rs @@ -45,7 +45,7 @@ impl AsMiscId for ParametersId { #[derive(Copy, Clone)] pub struct Bytecode_V1 { pub count: u16, - pub bytecode: *mut u32, + pub bytecode: *mut u32 } #[repr(C)] @@ -53,14 +53,14 @@ pub struct Bytecode_V1 { pub struct Bytecode_V2 { pub count: u16, unk_0: u32, - pub bytecode: *mut u32, + pub bytecode: *mut u32 } #[repr(C)] #[derive(Copy, Clone)] pub struct Locals_V1 { pub count: u16, - pub names: *const strings::VariableId, + pub names: *const strings::VariableId } #[repr(C)] @@ -68,14 +68,14 @@ pub struct Locals_V1 { pub struct Locals_V2 { pub count: u16, unk_0: u32, - pub names: *const strings::VariableId, + pub names: *const strings::VariableId } #[repr(C)] #[derive(Copy, Clone)] pub struct Parameters_V1 { params_count_mul_4: u16, - pub data: *const ParametersData, + pub data: *const ParametersData } #[repr(C)] @@ -83,7 +83,7 @@ pub struct Parameters_V1 { pub struct Parameters_V2 { params_count_mul_4: u16, unk_0: u32, - pub data: *const ParametersData, + pub data: *const ParametersData } #[repr(C)] @@ -91,7 +91,7 @@ pub struct Parameters_V2 { pub union Misc_V1 { pub bytecode: Bytecode_V1, pub locals: Locals_V1, - pub parameters: Parameters_V1, + pub parameters: Parameters_V1 } #[repr(C)] @@ -99,7 +99,7 @@ pub union Misc_V1 { pub union Misc_V2 { pub bytecode: Bytecode_V2, pub locals: Locals_V2, - pub parameters: Parameters_V2, + pub parameters: Parameters_V2 } #[repr(C)] @@ -107,7 +107,7 @@ pub struct ParametersData { unk_0: u32, unk_1: u32, pub name: strings::VariableId, - unk_4: u32, + unk_4: u32 } impl Parameters_V1 { diff --git a/auxtools/src/raw_types/procs.rs b/auxtools/src/raw_types/procs.rs index bac95530..d84b339c 100644 --- a/auxtools/src/raw_types/procs.rs +++ b/auxtools/src/raw_types/procs.rs @@ -1,8 +1,7 @@ -use super::misc; -use super::strings; -use super::values; use std::sync::OnceLock; +use super::{misc, strings, values}; + #[repr(C)] #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct ProcId(pub u32); @@ -15,12 +14,13 @@ pub struct ProcEntry { pub category: strings::StringId, flags: u32, unk_1: u32, - pub metadata: ProcMetadata, + pub metadata: ProcMetadata } +#[repr(C)] pub union ProcMetadata { pub pre1630: BytecodePre1630, - pub post1630: BytecodePost1630, + pub post1630: BytecodePost1630 } impl ProcMetadata { @@ -29,7 +29,7 @@ impl ProcMetadata { REDIRECT.get_or_init(|| unsafe { match crate::version::BYOND_VERSION_MINOR { ..=1627 => Self::get_bytecode_pre1630, - _ => Self::get_bytecode_post1630, + _ => Self::get_bytecode_post1630 } })(self) } @@ -49,7 +49,7 @@ impl ProcMetadata { REDIRECT.get_or_init(|| unsafe { match crate::version::BYOND_VERSION_MINOR { ..=1627 => Self::get_locals_pre1630, - _ => Self::get_locals_post1630, + _ => Self::get_locals_post1630 } })(self) } @@ -69,7 +69,7 @@ impl ProcMetadata { REDIRECT.get_or_init(|| unsafe { match crate::version::BYOND_VERSION_MINOR { ..=1627 => Self::get_parameters_pre1630, - _ => Self::get_parameters_post1630, + _ => Self::get_parameters_post1630 } })(self) } @@ -90,7 +90,7 @@ impl ProcMetadata { pub struct BytecodePre1630 { pub bytecode: misc::BytecodeId, pub locals: misc::LocalsId, - pub parameters: misc::ParametersId, + pub parameters: misc::ParametersId } #[repr(C)] @@ -98,9 +98,9 @@ pub struct BytecodePre1630 { pub struct BytecodePost1630 { unk_2: u32, pub bytecode: misc::BytecodeId, - //Bytecode moved by 4 bytes in 1630 + // Bytecode moved by 4 bytes in 1630 pub locals: misc::LocalsId, - pub parameters: misc::ParametersId, + pub parameters: misc::ParametersId } #[repr(C)] @@ -117,7 +117,7 @@ pub struct ProcInstance { pub args_count: u32, pub args: *mut values::Value, unk_3: [u8; 0x58], - pub time_to_resume: u32, + pub time_to_resume: u32 } #[repr(C)] @@ -151,17 +151,17 @@ pub struct ExecutionContext { infinite_loop_count: u32, unk_8: [u8; 0x02], paused: u8, - unk_9: [u8; 0x33], + unk_9: [u8; 0x33] } #[repr(C)] pub struct SuspendedProcsBuffer { - pub buffer: *mut *mut ProcInstance, + pub buffer: *mut *mut ProcInstance } #[repr(C)] pub struct SuspendedProcs { pub front: usize, pub back: usize, - pub capacity: usize, + pub capacity: usize } diff --git a/auxtools/src/raw_types/strings.rs b/auxtools/src/raw_types/strings.rs index 76caed58..8e218817 100644 --- a/auxtools/src/raw_types/strings.rs +++ b/auxtools/src/raw_types/strings.rs @@ -23,5 +23,5 @@ pub struct StringEntry { pub right: *mut StringEntry, pub ref_count: u32, pub unk_1: u32, - pub unk_2: u32, + pub unk_2: u32 } diff --git a/auxtools/src/raw_types/values.rs b/auxtools/src/raw_types/values.rs index 0b5b9c1a..8f3db677 100644 --- a/auxtools/src/raw_types/values.rs +++ b/auxtools/src/raw_types/values.rs @@ -1,8 +1,6 @@ -use super::funcs; -use super::lists; -use super::strings; -use std::ffi::CStr; -use std::fmt; +use std::{ffi::CStr, fmt}; + +use super::{funcs, lists, strings}; #[repr(u8)] #[derive(PartialEq, Copy, Clone, Debug, Hash)] @@ -63,7 +61,7 @@ pub enum ValueTag { SaveFile = 0x23, Number = 0x2A, - Appearance = 0x3A, + Appearance = 0x3A } impl fmt::Display for Value { @@ -78,7 +76,7 @@ impl fmt::Display for Value { assert_eq!(funcs::get_string_table_entry(&mut entry, id), 1); write!(f, "{:?}", CStr::from_ptr((*entry).data).to_string_lossy()) } - _ => write!(f, "Value({}, {})", self.tag as u8, self.data.id), + _ => write!(f, "Value({}, {})", self.tag as u8, self.data.id) } } } @@ -96,7 +94,7 @@ impl fmt::Debug for Value { assert_eq!(funcs::get_string_table_entry(&mut entry, id), 1); write!(f, "{:?}", CStr::from_ptr((*entry).data).to_string_lossy()) } - _ => write!(f, "Value({}, {})", self.tag as u8, self.data.id), + _ => write!(f, "Value({}, {})", self.tag as u8, self.data.id) } } } @@ -104,7 +102,7 @@ impl fmt::Debug for Value { impl fmt::Display for ValueTag { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - //write!(f, "{:?}", self) + // write!(f, "{:?}", self) write!(f, "TODO") } } @@ -115,13 +113,14 @@ pub union ValueData { pub string: strings::StringId, pub number: f32, pub id: u32, - pub list: lists::ListId, + pub list: lists::ListId } -/// Internal thing used when interfacing with BYOND. You shouldn't need to use this. +/// Internal thing used when interfacing with BYOND. You shouldn't need to use +/// this. #[repr(C)] #[derive(Copy, Clone)] pub struct Value { pub tag: ValueTag, - pub data: ValueData, + pub data: ValueData } diff --git a/auxtools/src/raw_types/variables.rs b/auxtools/src/raw_types/variables.rs index 07970fa9..3cfa256b 100644 --- a/auxtools/src/raw_types/variables.rs +++ b/auxtools/src/raw_types/variables.rs @@ -3,5 +3,5 @@ use super::strings; #[repr(C)] pub struct VariableNameIdTable { pub entries: *const strings::StringId, - pub count: u32, + pub count: u32 } diff --git a/auxtools/src/runtime.rs b/auxtools/src/runtime.rs index b09e346e..ca26a5d2 100644 --- a/auxtools/src/runtime.rs +++ b/auxtools/src/runtime.rs @@ -1,23 +1,25 @@ -use crate::value::Value; use std::result; -/// Represents a byond runtime, sort of. This will probably drastically in the future. +use crate::value::Value; + +/// Represents a byond runtime, sort of. This will probably drastically in the +/// future. /// -/// These are just simple error messages that our API and hooks can return as failure states. +/// These are just simple error messages that our API and hooks can return as +/// failure states. #[derive(Debug)] pub struct Runtime { - pub message: String, + pub message: String } impl Runtime { pub fn new>(message: S) -> Self { - Self { - message: message.into(), - } + Self { message: message.into() } } } -/// This macro makes instantiating [Runtimes](struct.Runtime.html) a (little bit) easier. +/// This macro makes instantiating [Runtimes](struct.Runtime.html) a (little +/// bit) easier. #[macro_export] macro_rules! runtime { ($fmt:expr) => { diff --git a/auxtools/src/sigscan.rs b/auxtools/src/sigscan.rs index 170092c7..044b4bbc 100644 --- a/auxtools/src/sigscan.rs +++ b/auxtools/src/sigscan.rs @@ -5,15 +5,13 @@ mod windows; use std::ops::{Bound, RangeBounds}; +pub use auxtools_impl::convert_signature; #[cfg(unix)] pub use linux::Scanner; +pub use once_cell; #[cfg(windows)] pub use windows::Scanner; -pub use auxtools_impl::convert_signature; - -pub use once_cell; - #[macro_export] macro_rules! signature { ($sig:tt) => { @@ -39,13 +37,13 @@ macro_rules! signature_struct { (call, $sig:tt) => { $crate::sigscan::Signature { treatment: $crate::sigscan::SignatureTreatment::OffsetByCall, - bytes: signature!($sig), + bytes: signature!($sig) } }; ($offset:literal, $sig:tt) => { $crate::sigscan::Signature { treatment: $crate::sigscan::SignatureTreatment::OffsetByInt($offset), - bytes: signature!($sig), + bytes: signature!($sig) } }; (($spec:tt, $sig:tt)) => { @@ -54,7 +52,7 @@ macro_rules! signature_struct { ($sig:tt) => { $crate::sigscan::Signature { treatment: $crate::sigscan::SignatureTreatment::NoOffset, - bytes: signature!($sig), + bytes: signature!($sig) } }; } @@ -111,7 +109,7 @@ macro_rules! find_signature { find_signature_inner!($scanner, $name, $type); }; - ($scanner:ident, ($name:ident as $type:ty)) => { + ($scanner:ident,($name:ident as $type:ty)) => { find_signature_inner!($scanner, $name, $type); }; @@ -126,7 +124,7 @@ macro_rules! find_signature_result { find_signature_inner_result!($scanner, $name, $type); }; - ($scanner:ident, ($name:ident as $type:ty)) => { + ($scanner:ident,($name:ident as $type:ty)) => { find_signature_inner_result!($scanner, $name, $type); }; @@ -156,24 +154,20 @@ macro_rules! find_signatures_result { pub enum SignatureTreatment { NoOffset, OffsetByInt(isize), - OffsetByCall, + OffsetByCall } pub struct Signature { pub treatment: SignatureTreatment, - pub bytes: &'static [Option], + pub bytes: &'static [Option] } impl Signature { pub fn find(&self, scanner: &Scanner) -> Option<*const std::ffi::c_void> { scanner.find(&self.bytes).map(|address| unsafe { match self.treatment { - SignatureTreatment::NoOffset | SignatureTreatment::OffsetByInt(0) => { - std::mem::transmute(address as *const std::ffi::c_void) - } - SignatureTreatment::OffsetByInt(i) => { - *(address.offset(i) as *const *const std::ffi::c_void) - } + SignatureTreatment::NoOffset | SignatureTreatment::OffsetByInt(0) => std::mem::transmute(address as *const std::ffi::c_void), + SignatureTreatment::OffsetByInt(i) => *(address.offset(i) as *const *const std::ffi::c_void), SignatureTreatment::OffsetByCall => { let offset = *(address.offset(1) as *const isize); address.offset(5).offset(offset) as *const () as *const std::ffi::c_void @@ -185,7 +179,7 @@ impl Signature { pub enum SignatureMap { AllVersions(Signature), - VersionDependent(Vec<((Bound<&'static u32>, Bound<&'static u32>), Signature)>), + VersionDependent(Vec<((Bound<&'static u32>, Bound<&'static u32>), Signature)>) } impl SignatureMap { @@ -195,7 +189,7 @@ impl SignatureMap { Self::VersionDependent(map) => map .iter() .find(|(version_range, _)| version_range.contains(&version)) - .and_then(|(_, signature)| signature.find(scanner)), + .and_then(|(_, signature)| signature.find(scanner)) } } } diff --git a/auxtools/src/sigscan/linux.rs b/auxtools/src/sigscan/linux.rs index 213b0a35..3446c0ec 100644 --- a/auxtools/src/sigscan/linux.rs +++ b/auxtools/src/sigscan/linux.rs @@ -1,5 +1,7 @@ -use std::ffi::{c_void, CStr, CString}; -use std::os::raw::{c_char, c_int}; +use std::{ + ffi::{c_void, CStr, CString}, + os::raw::{c_char, c_int} +}; use libc::{dl_iterate_phdr, dl_phdr_info, Elf32_Phdr, PT_LOAD}; @@ -8,31 +10,24 @@ struct CallbackData { module_name_ptr: *const c_char, memory_start: usize, memory_len: usize, - memory_area: Option<&'static [u8]>, + memory_area: Option<&'static [u8]> } pub struct Scanner { - module_name: String, + module_name: String } extern "C" fn dl_phdr_callback(info: *mut dl_phdr_info, _size: usize, data: *mut c_void) -> c_int { let info = unsafe { *info }; let module_name = unsafe { CStr::from_ptr(info.dlpi_name) }.to_str().unwrap(); let cb_data = unsafe { &mut *(data as *mut CallbackData) }; - let target_module_name = unsafe { CStr::from_ptr(cb_data.module_name_ptr as *mut c_char) } - .to_str() - .unwrap(); + let target_module_name = unsafe { CStr::from_ptr(cb_data.module_name_ptr as *mut c_char) }.to_str().unwrap(); if !module_name.ends_with(target_module_name) { return 0; } - let headers: &'static [Elf32_Phdr] = - unsafe { std::slice::from_raw_parts(info.dlpi_phdr, info.dlpi_phnum as usize) }; - let elf_header = headers - .iter() - .filter(|p| p.p_type == PT_LOAD) - .next() - .unwrap(); + let headers: &'static [Elf32_Phdr] = unsafe { std::slice::from_raw_parts(info.dlpi_phdr, info.dlpi_phnum as usize) }; + let elf_header = headers.iter().filter(|p| p.p_type == PT_LOAD).next().unwrap(); let start = (info.dlpi_addr + elf_header.p_vaddr) as usize; let end = start + elf_header.p_memsz as usize; @@ -47,7 +42,7 @@ extern "C" fn dl_phdr_callback(info: *mut dl_phdr_info, _size: usize, data: *mut impl Scanner { pub fn for_module(name: &str) -> Option { Some(Scanner { - module_name: name.to_string(), + module_name: name.to_string() }) } @@ -58,14 +53,9 @@ impl Scanner { module_name_ptr, memory_start: 0, memory_len: 0, - memory_area: None, - }; - unsafe { - dl_iterate_phdr( - Some(dl_phdr_callback), - &mut data as *mut CallbackData as *mut c_void, - ) + memory_area: None }; + unsafe { dl_iterate_phdr(Some(dl_phdr_callback), &mut data as *mut CallbackData as *mut c_void) }; let mut data_current = data.memory_start as *mut u8; let data_end = (data.memory_start + data.memory_len) as *mut u8; @@ -80,9 +70,7 @@ impl Scanner { unsafe { while data_current <= data_end { - if signature[signature_offset] == None - || signature[signature_offset] == Some(*data_current) - { + if signature[signature_offset] == None || signature[signature_offset] == Some(*data_current) { if signature.len() <= signature_offset + 1 { if result.is_some() { // Found two matches. diff --git a/auxtools/src/sigscan/windows.rs b/auxtools/src/sigscan/windows.rs index 396eb6f8..0208df29 100644 --- a/auxtools/src/sigscan/windows.rs +++ b/auxtools/src/sigscan/windows.rs @@ -1,15 +1,14 @@ -use std::mem; -use std::ptr; +use std::{mem, ptr}; -use winapi::shared::minwindef; -use winapi::um::libloaderapi; -use winapi::um::processthreadsapi; -use winapi::um::psapi; +use winapi::{ + shared::minwindef, + um::{libloaderapi, processthreadsapi, psapi} +}; pub struct Scanner { _module: minwindef::HMODULE, data_begin: *mut u8, - data_end: *mut u8, + data_end: *mut u8 } impl Scanner { @@ -31,7 +30,7 @@ impl Scanner { processthreadsapi::GetCurrentProcess(), module, module_info_wrapper.as_mut_ptr(), - mem::size_of::() as u32, + mem::size_of::() as u32 ) == 0 { libloaderapi::FreeLibrary(module); @@ -40,15 +39,13 @@ impl Scanner { let module_info = module_info_wrapper.assume_init(); data_begin = module_info.lpBaseOfDll as *mut u8; - data_end = data_begin - .offset(module_info.SizeOfImage as isize) - .offset(-1); + data_end = data_begin.offset(module_info.SizeOfImage as isize).offset(-1); } Some(Scanner { _module: module, data_begin, - data_end, + data_end }) } @@ -60,9 +57,7 @@ impl Scanner { unsafe { while data_current <= data_end { - if signature[signature_offset] == None - || signature[signature_offset] == Some(*data_current) - { + if signature[signature_offset] == None || signature[signature_offset] == Some(*data_current) { if signature.len() <= signature_offset + 1 { if result.is_some() { // Found two matches. @@ -90,11 +85,9 @@ impl Scanner { impl Drop for Scanner { fn drop(&mut self) { // TODO: WTf this started throwing?! - /* - unsafe { - libloaderapi::FreeLibrary(self.module); - } - */ + // unsafe { + // libloaderapi::FreeLibrary(self.module); + // } } } diff --git a/auxtools/src/string.rs b/auxtools/src/string.rs index d7ee0dc6..ef58239e 100644 --- a/auxtools/src/string.rs +++ b/auxtools/src/string.rs @@ -1,22 +1,22 @@ use crate::*; -use std::ffi::CStr; -use std::fmt; +use std::{ffi::CStr, fmt}; -/// A wrapper around [Values](struct.Value.html) that make working with strings a little easier +/// A wrapper around [Values](struct.Value.html) that make working with strings +/// a little easier pub struct StringRef { - pub value: Value, + pub value: Value } impl StringRef { pub fn new(string: &str) -> DMResult { Ok(StringRef { - value: Value::from_string(string)?, + value: Value::from_string(string)? }) } pub fn from_raw(data: &[u8]) -> DMResult { Ok(StringRef { - value: Value::from_string_raw(data)?, + value: Value::from_string_raw(data)? }) } @@ -25,9 +25,10 @@ impl StringRef { return None; } - // Here we're going from value -> raw -> new value because to get that juicy static lifetime + // Here we're going from value -> raw -> new value because to get that juicy + // static lifetime Some(StringRef { - value: unsafe { Value::from_raw(value.raw) }, + value: unsafe { Value::from_raw(value.raw) } }) } @@ -35,21 +36,19 @@ impl StringRef { StringRef { value: Value::from_raw(raw_types::values::Value { tag: raw_types::values::ValueTag::String, - data: raw_types::values::ValueData { string: id }, - }), + data: raw_types::values::ValueData { string: id } + }) } } pub unsafe fn from_variable_id(id: raw_types::strings::VariableId) -> Self { - let string_id = *((*raw_types::funcs::VARIABLE_NAMES) - .entries - .add(id.0 as usize)); + let string_id = *((*raw_types::funcs::VARIABLE_NAMES).entries.add(id.0 as usize)); StringRef { value: Value::from_raw(raw_types::values::Value { tag: raw_types::values::ValueTag::String, - data: raw_types::values::ValueData { string: string_id }, - }), + data: raw_types::values::ValueData { string: string_id } + }) } } @@ -88,11 +87,12 @@ impl fmt::Debug for StringRef { loop { let byte = match iter.next() { Some(x) => *x, - None => break, + None => break }; if byte == 0xFF { - // NOTE: Doesn't hold state for formatting, so some strings relying on are a little off + // NOTE: Doesn't hold state for formatting, so some strings relying on are a + // little off format.extend_from_slice(match iter.next() { None => break, Some(1) | Some(2) | Some(3) | Some(4) => b"[]", @@ -137,7 +137,7 @@ impl fmt::Debug for StringRef { Some(43) => b"\\icon[]", Some(44) => b"\\roman[]", Some(45) => b"\\Roman[]", - Some(_) => b"[UNKNONWN FORMAT SPECIFIER]", + Some(_) => b"[UNKNONWN FORMAT SPECIFIER]" }); continue; } diff --git a/auxtools/src/string_intern.rs b/auxtools/src/string_intern.rs index a21ed3e0..22e43836 100644 --- a/auxtools/src/string_intern.rs +++ b/auxtools/src/string_intern.rs @@ -1,14 +1,12 @@ use std::cell::UnsafeCell; -use crate::inventory; -use crate::StringRef; +use crate::{inventory, StringRef}; #[macro_export] macro_rules! byond_string { ($s:literal) => { unsafe { - static mut STORE: $crate::InternedString = - $crate::InternedString($s, std::cell::UnsafeCell::new(None)); + static mut STORE: $crate::InternedString = $crate::InternedString($s, std::cell::UnsafeCell::new(None)); $crate::inventory::submit!(unsafe { &STORE }); let x = &*STORE.1.get(); x.as_ref().unwrap() @@ -16,7 +14,7 @@ macro_rules! byond_string { }; } -//hack +// hack unsafe impl Sync for InternedString {} #[doc(hidden)] diff --git a/auxtools/src/value.rs b/auxtools/src/value.rs index 4543d02f..a653b97f 100644 --- a/auxtools/src/value.rs +++ b/auxtools/src/value.rs @@ -1,18 +1,15 @@ -use super::raw_types; -use super::string; -use crate::list; -use crate::runtime; -use crate::runtime::DMResult; -use std::ffi::CString; -use std::fmt; -use std::marker::PhantomData; - -/// `Value` represents any value a DM variable can hold, such as numbers, strings, datums, etc. +use super::{raw_types, string}; +use crate::{list, runtime, runtime::DMResult}; +use std::{ffi::CString, fmt, marker::PhantomData}; + +/// `Value` represents any value a DM variable can hold, such as numbers, +/// strings, datums, etc. /// -/// There's a lot of lifetime shenanigans going on, the gist of it is to just not keep Values around for longer than your hook's execution. +/// There's a lot of lifetime shenanigans going on, the gist of it is to just +/// not keep Values around for longer than your hook's execution. pub struct Value { pub raw: raw_types::values::Value, - phantom: PhantomData<*mut ()>, + phantom: PhantomData<*mut ()> } impl PartialEq for Value { @@ -43,16 +40,13 @@ impl Drop for Value { impl Value { /// Creates a new value from raw tag and data. /// Use if you know what you are doing. - pub unsafe fn new( - tag: raw_types::values::ValueTag, - data: raw_types::values::ValueData, - ) -> Value { + pub unsafe fn new(tag: raw_types::values::ValueTag, data: raw_types::values::ValueData) -> Value { let raw = raw_types::values::Value { tag, data }; raw_types::funcs::inc_ref_count(raw); Value { raw, - phantom: PhantomData {}, + phantom: PhantomData {} } } @@ -61,9 +55,9 @@ impl Value { Value { raw: raw_types::values::Value { tag: raw_types::values::ValueTag::World, - data: raw_types::values::ValueData { id: 1 }, + data: raw_types::values::ValueData { id: 1 } }, - phantom: PhantomData {}, + phantom: PhantomData {} } } @@ -72,9 +66,9 @@ impl Value { Value { raw: raw_types::values::Value { tag: raw_types::values::ValueTag::World, - data: raw_types::values::ValueData { id: 0 }, + data: raw_types::values::ValueData { id: 0 } }, - phantom: PhantomData {}, + phantom: PhantomData {} } } @@ -83,22 +77,24 @@ impl Value { Value { raw: raw_types::values::Value { tag: raw_types::values::ValueTag::Null, - data: raw_types::values::ValueData { number: 0.0 }, + data: raw_types::values::ValueData { number: 0.0 } }, - phantom: PhantomData {}, + phantom: PhantomData {} } } - /// Gets a turf by ID, without bounds checking. Use turf_by_id if you're not sure about how to check the bounds. + /// Gets a turf by ID, without bounds checking. Use turf_by_id if you're not + /// sure about how to check the bounds. pub unsafe fn turf_by_id_unchecked(id: u32) -> Value { Value { raw: raw_types::values::Value { tag: raw_types::values::ValueTag::Turf, - data: raw_types::values::ValueData { id }, + data: raw_types::values::ValueData { id } }, - phantom: PhantomData {}, + phantom: PhantomData {} } } + /// Gets a turf by ID, with bounds checking. pub fn turf_by_id(id: u32) -> DMResult { let world = Value::world(); @@ -124,19 +120,14 @@ impl Value { if (0..max_x).contains(&x) && (0..max_y).contains(&y) && (0..max_z).contains(&z) { Ok(unsafe { Value::turf_by_id_unchecked(x + y * max_x + z * max_x * max_y) }) } else { - Err(runtime!( - "Attempted to get out-of-range tile at coords {} {} {}", - x + 1, - y + 1, - z + 1 - )) + Err(runtime!("Attempted to get out-of-range tile at coords {} {} {}", x + 1, y + 1, z + 1)) } } fn get_by_id(&self, name_id: raw_types::strings::StringId) -> DMResult { let mut val = raw_types::values::Value { tag: raw_types::values::ValueTag::Null, - data: raw_types::values::ValueData { id: 0 }, + data: raw_types::values::ValueData { id: 0 } }; unsafe { @@ -149,11 +140,7 @@ impl Value { } } - fn set_by_id( - &self, - name_id: raw_types::strings::StringId, - new_value: raw_types::values::Value, - ) -> Result<(), runtime::Runtime> { + fn set_by_id(&self, name_id: raw_types::strings::StringId, new_value: raw_types::values::Value) -> Result<(), runtime::Runtime> { unsafe { if raw_types::funcs::set_variable(self.raw, name_id, new_value) != 1 { let varname: String = string::StringRef::from_id(name_id).into(); @@ -186,11 +173,7 @@ impl Value { } /// Sets a variable by name to a given value. - pub fn set, V: Into>( - &self, - name: S, - value: V, - ) -> DMResult<()> { + pub fn set, V: Into>(&self, name: S, value: V) -> DMResult<()> { let value = value.into(); self.set_by_id(name.into().get_id(), value.raw)?; @@ -201,17 +184,15 @@ impl Value { pub fn as_number(&self) -> DMResult { match self.raw.tag { raw_types::values::ValueTag::Number => unsafe { Ok(self.raw.data.number) }, - _ => Err(runtime!("Attempt to interpret non-number value as number")), + _ => Err(runtime!("Attempt to interpret non-number value as number")) } } /// Check if the current value is a string and casts it. pub fn as_string(&self) -> DMResult { match self.raw.tag { - raw_types::values::ValueTag::String => unsafe { - Ok(string::StringRef::from_id(self.raw.data.string).into()) - }, - _ => Err(runtime!("Attempt to interpret non-string value as String")), + raw_types::values::ValueTag::String => unsafe { Ok(string::StringRef::from_id(self.raw.data.string).into()) }, + _ => Err(runtime!("Attempt to interpret non-string value as String")) } } @@ -231,7 +212,7 @@ impl Value { pub fn call>(&self, procname: S, args: &[&Value]) -> DMResult { let mut ret = raw_types::values::Value { tag: raw_types::values::ValueTag::Null, - data: raw_types::values::ValueData { id: 0 }, + data: raw_types::values::ValueData { id: 0 } }; unsafe { @@ -253,7 +234,7 @@ impl Value { args.as_mut_ptr(), args.len(), 0, - 0, + 0 ) == 1 { return Ok(Value::from_raw_owned(ret)); @@ -266,9 +247,7 @@ impl Value { // ugh pub fn to_dmstring(&self) -> DMResult { match self.raw.tag { - raw_types::values::ValueTag::Null - | raw_types::values::ValueTag::Number - | raw_types::values::ValueTag::String => { + raw_types::values::ValueTag::Null | raw_types::values::ValueTag::Number | raw_types::values::ValueTag::String => { return Ok(string::StringRef::new(format!("{}", self.raw).as_str())?) } @@ -287,9 +266,9 @@ impl Value { pub fn to_string(&self) -> DMResult { match self.raw.tag { - raw_types::values::ValueTag::Null - | raw_types::values::ValueTag::Number - | raw_types::values::ValueTag::String => return Ok(format!("{}", self.raw)), + raw_types::values::ValueTag::Null | raw_types::values::ValueTag::Number | raw_types::values::ValueTag::String => { + return Ok(format!("{}", self.raw)) + } _ => {} } @@ -313,7 +292,7 @@ impl Value { pub fn is_exact_type>(&self, typepath: S) -> bool { match self.get_type() { Err(_) => false, - Ok(my_type) => my_type == typepath.as_ref(), + Ok(my_type) => my_type == typepath.as_ref() } } @@ -322,7 +301,7 @@ impl Value { raw_types::values::ValueTag::Null => false, raw_types::values::ValueTag::Number => unsafe { self.raw.data.number != 0.0 }, - _ => true, + _ => true } } @@ -334,34 +313,30 @@ impl Value { /// let my_string = Value::from_string("Testing!"); /// ``` pub fn from_string>(data: S) -> DMResult { - let string = CString::new(data.as_ref()) - .map_err(|_| runtime!("tried to create string containing NUL"))?; + let string = CString::new(data.as_ref()).map_err(|_| runtime!("tried to create string containing NUL"))?; unsafe { let mut id = raw_types::strings::StringId(0); assert_eq!(raw_types::funcs::get_string_id(&mut id, string.as_ptr()), 1); - Ok(Value::new( - raw_types::values::ValueTag::String, - raw_types::values::ValueData { string: id }, - )) + Ok(Value::new(raw_types::values::ValueTag::String, raw_types::values::ValueData { + string: id + })) } } pub fn from_string_raw(data: &[u8]) -> DMResult { - let string = - CString::new(data).map_err(|_| runtime!("tried to create string containing NUL"))?; + let string = CString::new(data).map_err(|_| runtime!("tried to create string containing NUL"))?; unsafe { let mut id = raw_types::strings::StringId(0); assert_eq!(raw_types::funcs::get_string_id(&mut id, string.as_ptr()), 1); - Ok(Value::new( - raw_types::values::ValueTag::String, - raw_types::values::ValueData { string: id }, - )) + Ok(Value::new(raw_types::values::ValueTag::String, raw_types::values::ValueData { + string: id + })) } } @@ -370,11 +345,12 @@ impl Value { Value::new(v.tag, v.data) } - /// same as from_raw but does not increment the reference count (assumes we already own this reference) + /// same as from_raw but does not increment the reference count (assumes we + /// already own this reference) pub unsafe fn from_raw_owned(v: raw_types::values::Value) -> Value { Value { raw: v, - phantom: PhantomData {}, + phantom: PhantomData {} } } } diff --git a/auxtools/src/value_from.rs b/auxtools/src/value_from.rs index 9129b7d5..edb89de5 100644 --- a/auxtools/src/value_from.rs +++ b/auxtools/src/value_from.rs @@ -1,53 +1,30 @@ -use crate::raw_types; -use crate::runtime::Runtime; -use crate::string; -use crate::List; -use crate::Value; -use std::collections::HashMap; -use std::convert::TryFrom; +use crate::{raw_types, runtime::Runtime, string, List, Value}; +use std::{collections::HashMap, convert::TryFrom}; impl From for Value { fn from(num: f32) -> Self { - unsafe { - Value::new( - raw_types::values::ValueTag::Number, - raw_types::values::ValueData { number: num }, - ) - } + unsafe { Value::new(raw_types::values::ValueTag::Number, raw_types::values::ValueData { number: num }) } } } impl From for Value { fn from(num: i32) -> Self { - unsafe { - Value::new( - raw_types::values::ValueTag::Number, - raw_types::values::ValueData { number: num as f32 }, - ) - } + unsafe { Value::new(raw_types::values::ValueTag::Number, raw_types::values::ValueData { number: num as f32 }) } } } impl From for Value { fn from(num: u32) -> Self { - unsafe { - Value::new( - raw_types::values::ValueTag::Number, - raw_types::values::ValueData { number: num as f32 }, - ) - } + unsafe { Value::new(raw_types::values::ValueTag::Number, raw_types::values::ValueData { number: num as f32 }) } } } impl From for Value { fn from(b: bool) -> Self { unsafe { - Value::new( - raw_types::values::ValueTag::Number, - raw_types::values::ValueData { - number: if b { 1.0 } else { 0.0 }, - }, - ) + Value::new(raw_types::values::ValueTag::Number, raw_types::values::ValueData { + number: if b { 1.0 } else { 0.0 } + }) } } } @@ -58,10 +35,11 @@ impl From<&Value> for Value { } } -/* List-y helpers */ +// List-y helpers // This is broken due to https://github.com/rust-lang/rust/issues/50133 -// The blanket implementation of TryFrom in core conflicts with -any- generics on a TryFrom trait +// The blanket implementation of TryFrom in core conflicts with -any- generics +// on a TryFrom trait // // impl> TryFrom for Value { // type Error = Runtime; @@ -73,6 +51,7 @@ impl From<&Value> for Value { // Specialized for ease-of-use due to the above not being possible impl + Clone> TryFrom<&HashMap> for Value { type Error = Runtime; + fn try_from(hashmap: &HashMap) -> Result { let res = List::new(); @@ -87,6 +66,7 @@ impl + Clone> TryFrom<&HashMap> for Value { impl + Clone, B: Into + Clone> TryFrom<&HashMap> for Value { type Error = Runtime; + fn try_from(hashmap: &HashMap) -> Result { let res = List::new(); diff --git a/auxtools/src/version.rs b/auxtools/src/version.rs index 428c5abd..70ceff66 100644 --- a/auxtools/src/version.rs +++ b/auxtools/src/version.rs @@ -1,6 +1,5 @@ use super::*; -use std::ffi::CString; -use std::os::raw::c_char; +use std::{ffi::CString, os::raw::c_char}; pub static mut BYOND_VERSION_MAJOR: u32 = 0; pub static mut BYOND_VERSION_MINOR: u32 = 0; @@ -32,20 +31,14 @@ pub fn init() -> Result<(), String> { return Err("Couldn't get module handle for BYONDCORE".into()); } - let symbol = libloaderapi::GetProcAddress( - module, - GET_BYOND_VERSION_SYMBOL.as_ptr() as *const c_char, - ); + let symbol = libloaderapi::GetProcAddress(module, GET_BYOND_VERSION_SYMBOL.as_ptr() as *const c_char); if symbol.is_null() { return Err("Couldn't find get_byond_version in BYONDCORE".into()); } get_byond_version = std::mem::transmute(symbol); - let symbol = libloaderapi::GetProcAddress( - module, - GET_BYOND_BUILD_SYMBOL.as_ptr() as *const c_char, - ); + let symbol = libloaderapi::GetProcAddress(module, GET_BYOND_BUILD_SYMBOL.as_ptr() as *const c_char); if symbol.is_null() { return Err("Couldn't find get_byond_build in BYONDCORE".into()); } diff --git a/auxtools/src/weak_value.rs b/auxtools/src/weak_value.rs index 9b5c29e9..daf9508d 100644 --- a/auxtools/src/weak_value.rs +++ b/auxtools/src/weak_value.rs @@ -1,12 +1,9 @@ -use crate::byond_string; -use crate::raw_types; -use crate::DMResult; -use crate::Value; -use std::sync::atomic::AtomicU32; -use std::sync::atomic::Ordering::Relaxed; +use crate::{byond_string, raw_types, DMResult, Value}; +use std::sync::atomic::{AtomicU32, Ordering::Relaxed}; fn get_next_id() -> f32 { - // This can (should) be only called from the main thread but we need to shut Rust up. + // This can (should) be only called from the main thread but we need to shut + // Rust up. static NEXT_WEAKREF_ID: AtomicU32 = AtomicU32::new(1); let id = NEXT_WEAKREF_ID.fetch_add(1, Relaxed); id as f32 @@ -15,8 +12,8 @@ fn get_next_id() -> f32 { /// A weak reference to some datum or atom in the game. /// /// Normal [`Value`]s are not safe to move between threads. -/// Using methods like [`Value::set`] or [`Value::call`] can at best cause undefined behavior, -/// at worst crash the server. +/// Using methods like [`Value::set`] or [`Value::call`] can at best cause +/// undefined behavior, at worst crash the server. /// /// A way to bypass that limitation is to store a raw value /// and use [`Value::from_raw`] on the main thread to actually work @@ -35,7 +32,8 @@ fn get_next_id() -> f32 { /// [`WeakValue::upgrade`] on another thread and invoke undefined behavior with /// the resulting [`Value`]. So, don't do that. /// -/// Using this struct requires all datums to have a `__auxtools_weakref_id` variable. +/// Using this struct requires all datums to have a `__auxtools_weakref_id` +/// variable. /// /// # Example /// ```ignore @@ -46,13 +44,13 @@ fn get_next_id() -> f32 { /// /// let weakref = callbacks.get(some_id); /// if let Some(thing) = weakref.upgrade() { -/// thing.call("callback", &[])?; +/// thing.call("callback", &[])?; /// } /// ``` #[derive(Copy, Clone)] pub struct WeakValue { inner: raw_types::values::Value, - id: f32, + id: f32 } impl WeakValue { @@ -71,9 +69,7 @@ impl WeakValue { /// and checks if it has been deleted in the meantime. pub fn upgrade(&self) -> Option { let real_val = unsafe { Value::from_raw(self.inner) }; - let id = real_val - .get_number(byond_string!("__auxtools_weakref_id")) - .ok()?; + let id = real_val.get_number(byond_string!("__auxtools_weakref_id")).ok()?; if self.id != id { return None; @@ -82,12 +78,12 @@ impl WeakValue { Some(real_val) } - /// Same as [`WeakValue::upgrade`] but returns a null if the datum was deleted, - /// so you can pass it straight into DM. + /// Same as [`WeakValue::upgrade`] but returns a null if the datum was + /// deleted, so you can pass it straight into DM. pub fn upgrade_or_null(&self) -> Value { match self.upgrade() { Some(v) => v, - None => Value::null(), + None => Value::null() } } } diff --git a/debug_server/Cargo.toml b/debug_server/Cargo.toml index 102f0b2f..d39d58b2 100644 --- a/debug_server/Cargo.toml +++ b/debug_server/Cargo.toml @@ -1,9 +1,12 @@ [package] name = "debug_server" -version = "2.3.2" -authors = ["Sophie Wallace "] -edition = "2018" +version = "2.3.3" publish = false +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +repository.workspace = true +license.workspace = true [lib] crate-type = ["cdylib"] diff --git a/debug_server/src/assemble_env.rs b/debug_server/src/assemble_env.rs index 57340e3e..16229c5b 100644 --- a/debug_server/src/assemble_env.rs +++ b/debug_server/src/assemble_env.rs @@ -45,13 +45,7 @@ impl dmasm::assembler::AssembleEnv for AssembleEnv { let proc = Proc::find("/proc/auxtools_expr_stub")?; proc.set_bytecode(assembly); - let res = proc - .call(&[&path]) - .unwrap() - .as_list() - .unwrap() - .get(1) - .unwrap(); + let res = proc.call(&[&path]).unwrap().as_list().unwrap().get(1).unwrap(); if res == Value::null() { return None; diff --git a/debug_server/src/ckey_override.rs b/debug_server/src/ckey_override.rs index 7973f746..a21fcf3b 100644 --- a/debug_server/src/ckey_override.rs +++ b/debug_server/src/ckey_override.rs @@ -1,7 +1,7 @@ -use region::Protection; use std::{ffi::CString, os::raw::c_char}; use auxtools::*; +use region::Protection; static mut STRING_PTR: *mut *const c_char = std::ptr::null_mut(); @@ -27,7 +27,7 @@ fn ckey_override_init() -> Result<(), String> { #[derive(Debug)] pub enum Error { UnsupportedByondVersion, - InvalidString, + InvalidString } pub fn override_guest_ckey(name: &str) -> Result<(), Error> { @@ -39,9 +39,7 @@ pub fn override_guest_ckey(name: &str) -> Result<(), Error> { let name = name.replace('%', "%%"); - let new_ptr = CString::new(name) - .map_err(|_| Error::InvalidString)? - .into_raw(); + let new_ptr = CString::new(name).map_err(|_| Error::InvalidString)?.into_raw(); unsafe { region::protect(STRING_PTR as *const u8, 4, Protection::READ_WRITE_EXECUTE).unwrap(); diff --git a/debug_server/src/crash_handler_windows.rs b/debug_server/src/crash_handler_windows.rs index b898645f..809e3f27 100644 --- a/debug_server/src/crash_handler_windows.rs +++ b/debug_server/src/crash_handler_windows.rs @@ -1,20 +1,18 @@ -use crate::{server_types::BreakpointReason, DEBUG_SERVER}; use auxtools::*; use winapi::{ shared::ntdef::LONG, um::{errhandlingapi::SetUnhandledExceptionFilter, winnt::EXCEPTION_POINTERS}, - vc::excpt::EXCEPTION_EXECUTE_HANDLER, + vc::excpt::EXCEPTION_EXECUTE_HANDLER }; +use crate::{server_types::BreakpointReason, DEBUG_SERVER}; + extern "system" fn exception_filter(_: *mut EXCEPTION_POINTERS) -> LONG { unsafe { if let Some(dbg) = &mut *DEBUG_SERVER.get() { let ctx = *raw_types::funcs::CURRENT_EXECUTION_CONTEXT; - dbg.handle_breakpoint( - ctx, - BreakpointReason::Runtime("native exception".to_owned()), - ); + dbg.handle_breakpoint(ctx, BreakpointReason::Runtime("native exception".to_owned())); } } diff --git a/debug_server/src/instruction_hooking.rs b/debug_server/src/instruction_hooking.rs index 03bf2da8..614e4bd0 100644 --- a/debug_server/src/instruction_hooking.rs +++ b/debug_server/src/instruction_hooking.rs @@ -1,17 +1,17 @@ -use crate::DEBUG_SERVER; -use crate::{ - server::Server, - server_types::{BreakpointReason, ContinueKind}, -}; +use std::{cell::UnsafeCell, collections::HashMap, sync::Mutex}; + use auxtools::*; use instruction_hooking::{ disassemble_env::{self, DisassembleEnv}, - InstructionHook, + InstructionHook }; use lazy_static::lazy_static; -use std::cell::UnsafeCell; -use std::collections::HashMap; -use std::sync::Mutex; + +use crate::{ + server::Server, + server_types::{BreakpointReason, ContinueKind}, + DEBUG_SERVER +}; // Could move these to dmasm const OPCODE_DBGLINE: u32 = 0x85; @@ -45,7 +45,8 @@ impl ProcInstanceRef { } } -// A lot of these store the parent ExecutionContext so we can tell if our proc has returned +// A lot of these store the parent ExecutionContext so we can tell if our proc +// has returned #[derive(Copy, Clone)] enum DebuggerAction { None, @@ -53,13 +54,12 @@ enum DebuggerAction { StepOver { target: ProcInstanceRef }, StepInto { parent: ProcInstanceRef }, BreakOnNext, - StepOut { target: ProcInstanceRef }, + StepOut { target: ProcInstanceRef } } static mut CURRENT_ACTION: DebuggerAction = DebuggerAction::None; -static mut DEFERRED_INSTRUCTION_REPLACE: UnsafeCell, *mut u32)>> = - UnsafeCell::new(None); +static mut DEFERRED_INSTRUCTION_REPLACE: UnsafeCell, *mut u32)>> = UnsafeCell::new(None); #[derive(PartialEq, Eq, Hash)] struct PtrKey(usize); @@ -107,14 +107,11 @@ fn get_proc_ctx(stack_id: u32) -> *mut raw_types::procs::ExecutionContext { } } -fn handle_breakpoint( - ctx: *mut raw_types::procs::ExecutionContext, - reason: BreakpointReason, -) -> DebuggerAction { +fn handle_breakpoint(ctx: *mut raw_types::procs::ExecutionContext, reason: BreakpointReason) -> DebuggerAction { let action = unsafe { match &mut *DEBUG_SERVER.get() { Some(server) => server.handle_breakpoint(ctx, reason), - None => ContinueKind::Continue, + None => ContinueKind::Continue } }; @@ -123,13 +120,13 @@ fn handle_breakpoint( ContinueKind::StepOver { stack_id } => { let ctx = get_proc_ctx(stack_id); DebuggerAction::StepOver { - target: ProcInstanceRef::new(unsafe { (*ctx).proc_instance }), + target: ProcInstanceRef::new(unsafe { (*ctx).proc_instance }) } } ContinueKind::StepInto { stack_id } => { let ctx = get_proc_ctx(stack_id); DebuggerAction::StepInto { - parent: ProcInstanceRef::new(unsafe { (*ctx).proc_instance }), + parent: ProcInstanceRef::new(unsafe { (*ctx).proc_instance }) } } ContinueKind::StepOut { stack_id } => { @@ -141,7 +138,7 @@ fn handle_breakpoint( DebuggerAction::None } else { DebuggerAction::StepOut { - target: ProcInstanceRef::new((*parent).proc_instance), + target: ProcInstanceRef::new((*parent).proc_instance) } } } @@ -149,10 +146,7 @@ fn handle_breakpoint( } } -fn proc_instance_is_in_stack( - mut ctx: *mut raw_types::procs::ExecutionContext, - proc_ref: ProcInstanceRef, -) -> bool { +fn proc_instance_is_in_stack(mut ctx: *mut raw_types::procs::ExecutionContext, proc_ref: ProcInstanceRef) -> bool { unsafe { let mut found = false; @@ -209,7 +203,8 @@ fn handle_runtime(error: &str) { impl InstructionHook for Server { fn handle_instruction(&mut self, ctx: *mut raw_types::procs::ExecutionContext) { - // Always handle the deferred instruction replacement first - everything else will depend on it + // Always handle the deferred instruction replacement first - everything else + // will depend on it unsafe { let deferred = DEFERRED_INSTRUCTION_REPLACE.get(); if let Some((src, dst)) = &*deferred { @@ -229,7 +224,8 @@ impl InstructionHook for Server { let opcode = unsafe { *opcode_ptr }; let is_dbgline = opcode == OPCODE_DBGLINE; - // This lets us ignore any actual breakpoints we hit if we've already paused for another reason + // This lets us ignore any actual breakpoints we hit if we've already paused for + // another reason let mut did_breakpoint = false; unsafe { @@ -257,9 +253,7 @@ impl InstructionHook for Server { } else { // If the context isn't in any stacks, it has just returned. Break! // TODO: Don't break if the context's stack is gone (returned to C) - if !proc_instance_is_in_stack(ctx, target) - && !proc_instance_is_suspended(target) - { + if !proc_instance_is_in_stack(ctx, target) && !proc_instance_is_suspended(target) { CURRENT_ACTION = DebuggerAction::None; CURRENT_ACTION = handle_breakpoint(ctx, BreakpointReason::Step); did_breakpoint = true; @@ -324,16 +318,14 @@ impl InstructionHook for Server { } } - // ORIGINAL_BYTECODE won't contain an entry if this breakpoint has already been removed + // ORIGINAL_BYTECODE won't contain an entry if this breakpoint has already been + // removed let map = ORIGINAL_BYTECODE.lock().unwrap(); if let Some(original) = map.get(&PtrKey::new(opcode_ptr)) { unsafe { let deferred_replace = DEFERRED_INSTRUCTION_REPLACE.get(); assert_eq!(*deferred_replace, None); - *deferred_replace = Some(( - std::slice::from_raw_parts(opcode_ptr, original.len()).to_vec(), - opcode_ptr, - )); + *deferred_replace = Some((std::slice::from_raw_parts(opcode_ptr, original.len()).to_vec(), opcode_ptr)); std::ptr::copy_nonoverlapping(original.as_ptr(), opcode_ptr, original.len()); } } @@ -343,14 +335,10 @@ impl InstructionHook for Server { #[derive(Debug)] pub enum InstructionHookError { - InvalidOffset, + InvalidOffset } -fn find_instruction<'a>( - env: &'a mut DisassembleEnv, - proc: &'a Proc, - offset: u32, -) -> Option<(dmasm::Instruction, dmasm::DebugData<'a>)> { +fn find_instruction<'a>(env: &'a mut DisassembleEnv, proc: &'a Proc, offset: u32) -> Option<(dmasm::Instruction, dmasm::DebugData<'a>)> { let bytecode = unsafe { proc.bytecode() }; let (nodes, _error) = dmasm::disassembler::disassemble(bytecode, env); @@ -368,8 +356,7 @@ fn find_instruction<'a>( pub fn hook_instruction(proc: &Proc, offset: u32) -> Result<(), InstructionHookError> { let mut env = disassemble_env::DisassembleEnv; - let (_, debug) = - find_instruction(&mut env, proc, offset).ok_or(InstructionHookError::InvalidOffset)?; + let (_, debug) = find_instruction(&mut env, proc, offset).ok_or(InstructionHookError::InvalidOffset)?; let instruction_length = debug.bytecode.len(); @@ -394,7 +381,7 @@ pub fn hook_instruction(proc: &Proc, offset: u32) -> Result<(), InstructionHookE unsafe { ORIGINAL_BYTECODE.lock().unwrap().insert( PtrKey::new(opcode_ptr), - std::slice::from_raw_parts(opcode_ptr, instruction_length as usize).to_vec(), + std::slice::from_raw_parts(opcode_ptr, instruction_length as usize).to_vec() ); } @@ -407,13 +394,12 @@ pub fn hook_instruction(proc: &Proc, offset: u32) -> Result<(), InstructionHookE #[derive(Debug)] pub enum InstructionUnhookError { - InvalidOffset, + InvalidOffset } pub fn unhook_instruction(proc: &Proc, offset: u32) -> Result<(), InstructionUnhookError> { let mut env = disassemble_env::DisassembleEnv; - let (_, _) = - find_instruction(&mut env, proc, offset).ok_or(InstructionUnhookError::InvalidOffset)?; + let (..) = find_instruction(&mut env, proc, offset).ok_or(InstructionUnhookError::InvalidOffset)?; let opcode_ptr = unsafe { let bytecode = { @@ -424,7 +410,8 @@ pub fn unhook_instruction(proc: &Proc, offset: u32) -> Result<(), InstructionUnh bytecode.as_mut_ptr().add(offset as usize) }; - // ORIGINAL_BYTECODE won't contain an entry if this breakpoint has already been removed + // ORIGINAL_BYTECODE won't contain an entry if this breakpoint has already been + // removed let mut map = ORIGINAL_BYTECODE.lock().unwrap(); if let Some(original) = map.get(&PtrKey::new(opcode_ptr)) { unsafe { diff --git a/debug_server/src/lib.rs b/debug_server/src/lib.rs index 1da49558..59d73e77 100644 --- a/debug_server/src/lib.rs +++ b/debug_server/src/lib.rs @@ -14,24 +14,23 @@ mod mem_profiler; #[cfg(not(windows))] mod mem_profiler_stub; -use ::instruction_hooking::{InstructionHook, INSTRUCTION_HOOKS}; -#[cfg(not(windows))] -use mem_profiler_stub as mem_profiler; - -pub(crate) use ::instruction_hooking::disassemble_env::DisassembleEnv; - use std::{ cell::UnsafeCell, - net::{IpAddr, Ipv4Addr, SocketAddr}, + net::{IpAddr, Ipv4Addr, SocketAddr} }; +pub(crate) use ::instruction_hooking::disassemble_env::DisassembleEnv; +use ::instruction_hooking::{InstructionHook, INSTRUCTION_HOOKS}; use auxtools::*; +#[cfg(not(windows))] +use mem_profiler_stub as mem_profiler; pub static mut DEBUG_SERVER: UnsafeCell> = UnsafeCell::new(None); #[shutdown] fn debugger_shutdown() { - // INSTRUCTION_HOOKS are cleared on shutdown so we don't need to worry about that. + // INSTRUCTION_HOOKS are cleared on shutdown so we don't need to worry about + // that. unsafe { DEBUG_SERVER.get_mut().take(); } @@ -40,19 +39,19 @@ fn debugger_shutdown() { fn get_default_mode() -> String { match std::env::var("AUXTOOLS_DEBUG_MODE") { Ok(val) => val, - Err(_) => "NONE".into(), + Err(_) => "NONE".into() } } fn get_default_port() -> u16 { match std::env::var("AUXTOOLS_DEBUG_PORT") { Ok(val) => val.parse::().unwrap_or(server_types::DEFAULT_PORT), - Err(_) => server_types::DEFAULT_PORT, + Err(_) => server_types::DEFAULT_PORT } } struct DebugServerInstructionHook<'a> { - debug_server: &'a mut UnsafeCell>, + debug_server: &'a mut UnsafeCell> } impl InstructionHook for DebugServerInstructionHook<'static> { @@ -66,10 +65,7 @@ impl InstructionHook for DebugServerInstructionHook<'static> { #[hook("/proc/enable_debugging")] fn enable_debugging(mode: Value, port: Value) { let mode = mode.as_string().unwrap_or_else(|_| get_default_mode()); - let port = port - .as_number() - .map(|x| x as u16) - .unwrap_or_else(|_| get_default_port()); + let port = port.as_number().map(|x| x as u16).unwrap_or_else(|_| get_default_port()); let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), port); @@ -78,15 +74,12 @@ fn enable_debugging(mode: Value, port: Value) { return Ok(Value::null()); } - "LAUNCHED" => server::Server::connect(&addr) - .map_err(|e| runtime!("Couldn't create debug server: {}", e))?, + "LAUNCHED" => server::Server::connect(&addr).map_err(|e| runtime!("Couldn't create debug server: {}", e))?, - "BACKGROUND" => server::Server::listen(&addr) - .map_err(|e| runtime!("Couldn't create debug server: {}", e))?, + "BACKGROUND" => server::Server::listen(&addr).map_err(|e| runtime!("Couldn't create debug server: {}", e))?, "BLOCK" => { - let mut server = server::Server::listen(&addr) - .map_err(|e| runtime!("Couldn't create debug server: {}", e))?; + let mut server = server::Server::listen(&addr).map_err(|e| runtime!("Couldn't create debug server: {}", e))?; server.process_until_configured(); // might never return 😳 server } @@ -100,12 +93,10 @@ fn enable_debugging(mode: Value, port: Value) { unsafe { *DEBUG_SERVER.get() = Some(server); debug_server_instruction_hook = DebugServerInstructionHook { - debug_server: &mut DEBUG_SERVER, + debug_server: &mut DEBUG_SERVER }; - INSTRUCTION_HOOKS - .get_mut() - .push(Box::new(debug_server_instruction_hook)); + INSTRUCTION_HOOKS.get_mut().push(Box::new(debug_server_instruction_hook)); } Ok(Value::null()) diff --git a/debug_server/src/mem_profiler.rs b/debug_server/src/mem_profiler.rs index 0ff74637..de33a308 100644 --- a/debug_server/src/mem_profiler.rs +++ b/debug_server/src/mem_profiler.rs @@ -1,9 +1,14 @@ -use detour::RawDetour; -use std::ffi::{c_void, CString}; -use std::os::raw::c_char; -use std::{cell::UnsafeCell, collections::HashMap, fs::File, io}; +use std::{ + cell::UnsafeCell, + collections::HashMap, + ffi::{c_void, CString}, + fs::File, + io, + os::raw::c_char +}; use auxtools::{raw_types::procs::ProcId, *}; +use detour::RawDetour; static mut THREAD_ID: u32 = 0; static MALLOC_SYMBOL: &[u8] = b"malloc\0"; @@ -33,21 +38,14 @@ fn setup_hooks() { return; } - let malloc = - libloaderapi::GetProcAddress(module, MALLOC_SYMBOL.as_ptr() as *const c_char); - let realloc = - libloaderapi::GetProcAddress(module, REALLOC_SYMBOL.as_ptr() as *const c_char); + let malloc = libloaderapi::GetProcAddress(module, MALLOC_SYMBOL.as_ptr() as *const c_char); + let realloc = libloaderapi::GetProcAddress(module, REALLOC_SYMBOL.as_ptr() as *const c_char); let free = libloaderapi::GetProcAddress(module, FREE_SYMBOL.as_ptr() as *const c_char); let new = libloaderapi::GetProcAddress(module, NEW_SYMBOL.as_ptr() as *const c_char); - let delete = - libloaderapi::GetProcAddress(module, DELETE_SYMBOL.as_ptr() as *const c_char); + let delete = libloaderapi::GetProcAddress(module, DELETE_SYMBOL.as_ptr() as *const c_char); // ¯\_(ツ)_/¯ - if malloc.is_null() - || realloc.is_null() - || free.is_null() - || new.is_null() || delete.is_null() - { + if malloc.is_null() || realloc.is_null() || free.is_null() || new.is_null() || delete.is_null() { return; } @@ -176,14 +174,14 @@ static mut STATE: UnsafeCell> = UnsafeCell::new(None); struct State { file: File, - live_allocs: HashMap<*const c_void, Allocation>, + live_allocs: HashMap<*const c_void, Allocation> } impl State { fn new(dump_path: &str) -> io::Result { Ok(State { file: File::create(dump_path)?, - live_allocs: HashMap::new(), + live_allocs: HashMap::new() }) } @@ -241,7 +239,7 @@ impl State { struct Allocation { proc: ProcId, - size: usize, + size: usize } pub fn begin(path: &str) -> io::Result<()> { diff --git a/debug_server/src/server.rs b/debug_server/src/server.rs index 2a0ffc06..b1a49fed 100644 --- a/debug_server/src/server.rs +++ b/debug_server/src/server.rs @@ -1,22 +1,26 @@ -use crate::mem_profiler; - -use super::instruction_hooking::{get_hooked_offsets, hook_instruction, unhook_instruction}; -use std::io::{Read, Write}; -use std::sync::mpsc; -use std::thread; -use std::{cell::RefCell, error::Error}; use std::{ + cell::RefCell, collections::HashMap, + error::Error, + io::{Read, Write}, net::{SocketAddr, TcpListener, TcpStream}, - thread::JoinHandle, + sync::mpsc, + thread, + thread::JoinHandle }; +use auxtools::{ + raw_types::values::{ValueData, ValueTag}, + * +}; use clap::{Arg, Command}; use instruction_hooking::disassemble_env; -use super::server_types::*; -use auxtools::raw_types::values::{ValueData, ValueTag}; -use auxtools::*; +use super::{ + instruction_hooking::{get_hooked_offsets, hook_instruction, unhook_instruction}, + server_types::* +}; +use crate::mem_profiler; #[derive(Clone, Hash, PartialEq, Eq)] enum Variables { @@ -24,13 +28,13 @@ enum Variables { Locals { frame: u32 }, ObjectVars(Value), ListContents(Value), - ListPair { key: Value, value: Value }, + ListPair { key: Value, value: Value } } struct State { stacks: debug::CallStacks, variables: RefCell>, - variables_to_refs: RefCell>, + variables_to_refs: RefCell> } impl State { @@ -38,7 +42,7 @@ impl State { Self { stacks: debug::CallStacks::new(), variables: RefCell::new(vec![]), - variables_to_refs: RefCell::new(HashMap::new()), + variables_to_refs: RefCell::new(HashMap::new()) } } @@ -59,19 +63,17 @@ impl State { fn get_variables(&self, reference: VariablesRef) -> Option { let variables = self.variables.borrow(); - variables - .get(reference.0 as usize - 1) - .map(|x| (*x).clone()) + variables.get(reference.0 as usize - 1).map(|x| (*x).clone()) } } -// // Server = main-thread code // ServerThread = networking-thread code // // We've got a couple of channels going on between Server/ServerThread -// connection: a TcpStream sent from the ServerThread for the Server to send responses on -// requests: requests from the debug-client for the Server to handle +// connection: a TcpStream sent from the ServerThread for the Server to send +// responses on requests: requests from the debug-client for the Server to +// handle // // Limitations: only ever accepts one connection // @@ -83,7 +85,7 @@ enum ServerStream { Connected(TcpStream), // The server has finished being used - Disconnected, + Disconnected } pub struct Server { @@ -95,11 +97,11 @@ pub struct Server { in_eval: bool, eval_error: Option, conditional_breakpoints: HashMap<(raw_types::procs::ProcId, u16), String>, - app: Command<'static>, + app: Command<'static> } struct ServerThread { - requests: mpsc::Sender, + requests: mpsc::Sender } impl Server { @@ -120,21 +122,18 @@ impl Server { .arg( Arg::new("proc") .help("Path of the proc to disassemble (e.g. /proc/do_stuff)") - .takes_value(true), + .takes_value(true) ) .arg( Arg::new("id") .help("Id of the proc to disassemble (for when multiple procs are defined with the same path)") - .takes_value(true), + .takes_value(true) ) ) .subcommand( Command::new("guest_override") .about("Override the CKey used by guest connections") - .arg( - Arg::new("ckey") - .takes_value(true), - ) + .arg(Arg::new("ckey").takes_value(true)) ) .subcommand( Command::new("mem_profiler") @@ -142,16 +141,9 @@ impl Server { .subcommand( Command::new("begin") .about("Begins memory profiling. Output goes to the specified file path") - .arg( - Arg::new("path") - .help("Where to output memory profiler results") - .takes_value(true), - ) - ) - .subcommand( - Command::new("end") - .about("Finishes current memory profiler.") + .arg(Arg::new("path").help("Where to output memory profiler results").takes_value(true)) ) + .subcommand(Command::new("end").about("Finishes current memory profiler.")) ) } @@ -159,9 +151,7 @@ impl Server { let stream = TcpStream::connect_timeout(&addr, std::time::Duration::from_secs(5))?; let (requests_sender, requests_receiver) = mpsc::channel(); - let server_thread = ServerThread { - requests: requests_sender, - }; + let server_thread = ServerThread { requests: requests_sender }; let cloned_stream = stream.try_clone().unwrap(); let thread = thread::spawn(move || { @@ -177,7 +167,7 @@ impl Server { in_eval: false, eval_error: None, conditional_breakpoints: HashMap::new(), - app: Self::setup_app(), + app: Self::setup_app() }; server.process_until_configured(); @@ -188,10 +178,7 @@ impl Server { let (connection_sender, connection_receiver) = mpsc::channel(); let (requests_sender, requests_receiver) = mpsc::channel(); - let thread = ServerThread { - requests: requests_sender, - } - .spawn_listener(TcpListener::bind(addr)?, connection_sender); + let thread = ServerThread { requests: requests_sender }.spawn_listener(TcpListener::bind(addr)?, connection_sender); Ok(Server { requests: requests_receiver, @@ -202,7 +189,7 @@ impl Server { in_eval: false, eval_error: None, conditional_breakpoints: HashMap::new(), - app: Self::setup_app(), + app: Self::setup_app() }) } @@ -250,7 +237,7 @@ impl Server { } } - None => None, + None => None } } @@ -302,7 +289,7 @@ impl Server { if List::is_list(value) { match List::from_value(value) { Ok(list) => format!("/list {{len = {}}}", list.len()), - Err(Runtime { message }) => format!("/list (failed to get len: {:?})", message), + Err(Runtime { message }) => format!("/list (failed to get len: {:?})", message) } } else { match value.to_string() { @@ -322,21 +309,17 @@ impl Server { Variable { name, value: stringified, - variables, + variables } } fn value_to_variables_ref(&self, value: &Value) -> Option { match self.state.as_ref() { - Some(state) if List::is_list(value) => { - Some(state.get_ref(Variables::ListContents(value.clone()))) - } + Some(state) if List::is_list(value) => Some(state.get_ref(Variables::ListContents(value.clone()))), - Some(state) if Self::is_object(value) => { - Some(state.get_ref(Variables::ObjectVars(value.clone()))) - } + Some(state) if Self::is_object(value) => Some(state.get_ref(Variables::ObjectVars(value.clone()))), - _ => None, + _ => None } } @@ -356,12 +339,8 @@ impl Server { if value.raw.tag != raw_types::values::ValueTag::Null { variables.push(Variable { name: format!("[{}]", i), - value: format!( - "{} = {}", - Self::stringify(&key), - Self::stringify(&value) - ), - variables: Some(state.get_ref(Variables::ListPair { key, value })), + value: format!("{} = {}", Self::stringify(&key), Self::stringify(&value)), + variables: Some(state.get_ref(Variables::ListPair { key, value })) }); continue; @@ -377,7 +356,8 @@ impl Server { } fn object_to_variables(&mut self, value: &Value) -> Result, Runtime> { - // Grab `value.vars`. We have a little hack for globals which use a special type. + // Grab `value.vars`. We have a little hack for globals which use a special + // type. let vars = List::from_value(&unsafe { if value.raw.tag == ValueTag::World && value.raw.data.id == 1 { Value::new(ValueTag::GlobalVars, ValueData { id: 0 }) @@ -400,7 +380,7 @@ impl Server { } } - //top_variables.sort_by_key(|a| a.name.to_lowercase()); + // top_variables.sort_by_key(|a| a.name.to_lowercase()); variables.sort_by_key(|a| a.name.to_lowercase()); top_variables.append(&mut variables); @@ -411,7 +391,7 @@ impl Server { let stack_id = stack_id as usize; let stacks = match &self.state { Some(state) => &state.stacks, - None => return None, + None => return None }; if stack_id == 0 { @@ -425,7 +405,7 @@ impl Server { let stack_id = stack_id as usize; let stacks = match &self.state { Some(state) => &state.stacks, - None => return 0, + None => return 0 }; if stack_id == 0 { @@ -445,7 +425,7 @@ impl Server { let mut frame_index = frame_index as usize; let stacks = match &self.state { Some(state) => &state.stacks, - None => return None, + None => return None }; if frame_index < stacks.active.len() { @@ -489,10 +469,7 @@ impl Server { } None => { - self.notify(format!( - "tried to read arguments from invalid frame id: {}", - frame_index - )); + self.notify(format!("tried to read arguments from invalid frame id: {}", frame_index)); vec![] } } @@ -511,10 +488,7 @@ impl Server { } None => { - self.notify(format!( - "tried to read locals from invalid frame id: {}", - frame_index - )); + self.notify(format!("tried to read locals from invalid frame id: {}", frame_index)); vec![] } } @@ -523,14 +497,11 @@ impl Server { fn handle_breakpoint_set(&mut self, instruction: InstructionRef, condition: Option) { let line = self.get_line_number(instruction.proc.clone(), instruction.offset); - let proc = match auxtools::Proc::find_override( - instruction.proc.path, - instruction.proc.override_id, - ) { + let proc = match auxtools::Proc::find_override(instruction.proc.path, instruction.proc.override_id) { Some(proc) => proc, None => { self.send_or_disconnect(Response::BreakpointSet { - result: BreakpointSetResult::Failed, + result: BreakpointSetResult::Failed }); return; } @@ -539,39 +510,34 @@ impl Server { match hook_instruction(&proc, instruction.offset) { Ok(()) => { if let Some(condition) = condition { - self.conditional_breakpoints - .insert((proc.id, instruction.offset as u16), condition); + self.conditional_breakpoints.insert((proc.id, instruction.offset as u16), condition); } self.send_or_disconnect(Response::BreakpointSet { - result: BreakpointSetResult::Success { line }, + result: BreakpointSetResult::Success { line } }); } Err(_) => { self.send_or_disconnect(Response::BreakpointSet { - result: BreakpointSetResult::Failed, + result: BreakpointSetResult::Failed }); } } } fn handle_breakpoint_unset(&mut self, instruction: InstructionRef) { - let proc = match auxtools::Proc::find_override( - instruction.proc.path, - instruction.proc.override_id, - ) { + let proc = match auxtools::Proc::find_override(instruction.proc.path, instruction.proc.override_id) { Some(proc) => proc, None => { self.send_or_disconnect(Response::BreakpointSet { - result: BreakpointSetResult::Failed, + result: BreakpointSetResult::Failed }); return; } }; - self.conditional_breakpoints - .remove(&(proc.id, instruction.offset as u16)); + self.conditional_breakpoints.remove(&(proc.id, instruction.offset as u16)); match unhook_instruction(&proc, instruction.offset) { Ok(()) => { @@ -590,20 +556,20 @@ impl Server { let mut ret = vec![]; ret.push(Stack { id: 0, - name: state.stacks.active[0].proc.path.clone(), + name: state.stacks.active[0].proc.path.clone() }); for (idx, stack) in state.stacks.suspended.iter().enumerate() { ret.push(Stack { id: (idx + 1) as u32, - name: stack[0].proc.path.clone(), + name: stack[0].proc.path.clone() }); } ret } - None => vec![], + None => vec![] }; self.send_or_disconnect(Response::Stacks { stacks }); @@ -628,22 +594,22 @@ impl Server { let proc_ref = ProcRef { path: stack[i].proc.path.to_owned(), - override_id: stack[i].proc.override_id(), + override_id: stack[i].proc.override_id() }; frames.push(StackFrame { id: frame_base + (i as u32), instruction: InstructionRef { proc: proc_ref.clone(), - offset: stack[i].offset as u32, + offset: stack[i].offset as u32 }, - line: self.get_line_number(proc_ref, stack[i].offset as u32), + line: self.get_line_number(proc_ref, stack[i].offset as u32) }); } Response::StackFrames { frames, - total_count: stack.len() as u32, + total_count: stack.len() as u32 } } @@ -651,7 +617,7 @@ impl Server { self.notify("received StackFrames request when not paused"); Response::StackFrames { frames: vec![], - total_count: 0, + total_count: 0 } } }; @@ -664,7 +630,7 @@ impl Server { let response = Response::Scopes { arguments: None, locals: None, - globals: None, + globals: None }; self.send_or_disconnect(response); @@ -681,7 +647,7 @@ impl Server { let response = Response::Scopes { arguments: Some(state.get_ref(arguments)), locals: Some(state.get_ref(locals)), - globals: Some(state.get_ref(globals)), + globals: Some(state.get_ref(globals)) }; self.send_or_disconnect(response); @@ -691,20 +657,15 @@ impl Server { let response = match &self.state { Some(state) => match state.get_variables(vars) { Some(vars) => match vars { - Variables::Arguments { frame } => Response::Variables { - vars: self.get_args(frame), - }, + Variables::Arguments { frame } => Response::Variables { vars: self.get_args(frame) }, Variables::Locals { frame } => Response::Variables { - vars: self.get_locals(frame), + vars: self.get_locals(frame) }, Variables::ObjectVars(value) => match self.object_to_variables(&value) { Ok(vars) => Response::Variables { vars }, Err(e) => { - self.notify(format!( - "runtime occured while processing Variables request: {:?}", - e - )); + self.notify(format!("runtime occured while processing Variables request: {:?}", e)); Response::Variables { vars: vec![] } } }, @@ -712,10 +673,7 @@ impl Server { Ok(vars) => Response::Variables { vars }, Err(e) => { - self.notify(format!( - "runtime occured while processing Variables request: {:?}", - e - )); + self.notify(format!("runtime occured while processing Variables request: {:?}", e)); Response::Variables { vars: vec![] } } }, @@ -724,8 +682,8 @@ impl Server { vars: vec![ self.value_to_variable("key".to_owned(), &key), self.value_to_variable("value".to_owned(), &value), - ], - }, + ] + } }, None => { @@ -745,19 +703,13 @@ impl Server { fn handle_command(&mut self, frame_id: Option, command: &str) -> String { // How many matches variables can you spot? It could be better... - let response = match self - .app - .try_get_matches_from_mut(command.split_ascii_whitespace()) - { + let response = match self.app.try_get_matches_from_mut(command.split_ascii_whitespace()) { Ok(matches) => { match matches.subcommand() { Some(("disassemble", matches)) => { if let Some(proc) = matches.value_of("proc") { // Default id to 0 in the worst way possible - let id = matches - .value_of("id") - .and_then(|x| x.parse::().ok()) - .unwrap_or(0); + let id = matches.value_of("id").and_then(|x| x.parse::().ok()).unwrap_or(0); self.handle_disassemble(proc, id) } else if let Some(frame_id) = frame_id { @@ -782,7 +734,7 @@ impl Server { } }, - None => "no ckey provided".to_owned(), + None => "no ckey provided".to_owned() }, Some(("mem_profiler", matches)) => match matches.subcommand() { @@ -791,7 +743,7 @@ impl Server { .map(|_| "Memory profiler enabled".to_owned()) .unwrap_or_else(|e| format!("Failed: {}", e)), - None => "no path provided".to_owned(), + None => "no path provided".to_owned() }, Some(("end", _)) => { @@ -799,13 +751,13 @@ impl Server { "Memory profiler disabled".to_owned() } - _ => "unknown memory profiler sub-command".to_owned(), + _ => "unknown memory profiler sub-command".to_owned() }, - _ => "unknown command".to_owned(), + _ => "unknown command".to_owned() } } - Err(e) => e.to_string(), + Err(e) => e.to_string() }; response @@ -817,7 +769,7 @@ impl Server { Usr, Src, Arg(u32), - Local(u32), + Local(u32) } let (ctx, instance, args) = match frame_id { @@ -828,10 +780,7 @@ impl Server { let frame = match self.get_stack_frame(frame_id) { Some(x) => x, None => { - self.notify(format!( - "tried to evaluate expression with invalid frame id: {}", - frame_id - )); + self.notify(format!("tried to evaluate expression with invalid frame id: {}", frame_id)); return None; } }; @@ -849,18 +798,14 @@ impl Server { } for (idx, local) in frame.locals.iter().enumerate() { - args.push(( - (&local.0).into(), - local.1.clone(), - ArgType::Local(idx as u32), - )); + args.push(((&local.0).into(), local.1.clone(), ArgType::Local(idx as u32))); } (frame.context, frame.instance, args) } }; - let arg_names: Vec<&str> = args.iter().map(|(name, _, _)| name.as_str()).collect(); + let arg_names: Vec<&str> = args.iter().map(|(name, ..)| name.as_str()).collect(); let arg_values: Vec<&Value> = args.iter().map(|(_, value, _)| value).collect(); let expr = match dmasm::compiler::compile_expr(command, &arg_names) { @@ -871,17 +816,13 @@ impl Server { } }; - let assembly = - match dmasm::assembler::assemble(&expr, &mut crate::assemble_env::AssembleEnv) { - Ok(assembly) => assembly, - Err(err) => { - self.notify(format!( - "expression {} failed to assemble: {:#?}", - command, err - )); - return None; - } - }; + let assembly = match dmasm::assembler::assemble(&expr, &mut crate::assemble_env::AssembleEnv) { + Ok(assembly) => assembly, + Err(err) => { + self.notify(format!("expression {} failed to assemble: {:#?}", command, err)); + return None; + } + }; let proc = match Proc::find("/proc/auxtools_expr_stub") { Some(proc) => proc, @@ -899,8 +840,8 @@ impl Server { let result = match proc.call(&arg_values) { Ok(res) => { if let Ok(list) = res.as_list() { - // The rest are the potentially mutated parameters. We need to commit them to the function that called us. - // TODO: This sucks, obviously. + // The rest are the potentially mutated parameters. We need to commit them to + // the function that called us. TODO: This sucks, obviously. let len = list.len(); for i in 2..=len { let value = list.get(i).unwrap(); @@ -945,10 +886,7 @@ impl Server { } Err(_) => { - self.notify(format!( - "Value::call failed when evaluating expression {}", - command - )); + self.notify(format!("Value::call failed when evaluating expression {}", command)); None } }; @@ -956,10 +894,7 @@ impl Server { self.in_eval = false; if let Some(err) = self.eval_error.take() { - self.notify(format!( - "runtime occured when executing expression: {}", - err - )); + self.notify(format!("runtime occured when executing expression: {}", err)); } result @@ -970,7 +905,7 @@ impl Server { let response = self.handle_command(frame_id, &command[1..]); self.send_or_disconnect(Response::Eval(EvalResponse { value: response, - variables: None, + variables: None })); return; } @@ -979,19 +914,19 @@ impl Server { Some(result) => { let variables = match context { Some(str) if str == "repl" => None, - _ => self.value_to_variables_ref(&result), + _ => self.value_to_variables_ref(&result) }; self.send_or_disconnect(Response::Eval(EvalResponse { value: Self::stringify(&result), - variables, + variables })); } None => { self.send_or_disconnect(Response::Eval(EvalResponse { value: "".to_owned(), - variables: None, + variables: None })); } } @@ -1028,7 +963,7 @@ impl Server { } } - None => "Proc not found".to_owned(), + None => "Proc not found".to_owned() }; return response; @@ -1039,35 +974,28 @@ impl Server { match request { Request::Disconnect => unreachable!(), Request::CatchRuntimes { should_catch } => self.should_catch_runtimes = should_catch, - Request::BreakpointSet { - instruction, - condition, - } => self.handle_breakpoint_set(instruction, condition), + Request::BreakpointSet { instruction, condition } => self.handle_breakpoint_set(instruction, condition), Request::BreakpointUnset { instruction } => self.handle_breakpoint_unset(instruction), Request::Stacks => self.handle_stacks(), Request::Scopes { frame_id } => self.handle_scopes(frame_id), Request::Variables { vars } => self.handle_variables(vars), - Request::Eval { - frame_id, - command, - context, - } => self.handle_eval(frame_id, &command, context), + Request::Eval { frame_id, command, context } => self.handle_eval(frame_id, &command, context), Request::StackFrames { stack_id, start_frame, - count, + count } => self.handle_stack_frames(stack_id, start_frame, count), Request::LineNumber { proc, offset } => { self.send_or_disconnect(Response::LineNumber { - line: self.get_line_number(proc, offset), + line: self.get_line_number(proc, offset) }); } Request::Offset { proc, line } => { self.send_or_disconnect(Response::Offset { - offset: self.get_offset(proc, line), + offset: self.get_offset(proc, line) }); } @@ -1086,12 +1014,12 @@ impl Server { Some(frame) => Some(InstructionRef { proc: ProcRef { path: frame.proc.path.to_owned(), - override_id: frame.proc.override_id(), + override_id: frame.proc.override_id() }, - offset: frame.offset as u32, + offset: frame.offset as u32 }), - None => None, + None => None }; self.send_or_disconnect(Response::CurrentInstruction(response)); @@ -1129,7 +1057,7 @@ impl Server { } } - _ => (), + _ => () } } @@ -1144,11 +1072,7 @@ impl Server { self.send_or_disconnect(Response::Notification { message }); } - pub fn handle_breakpoint( - &mut self, - _ctx: *mut raw_types::procs::ExecutionContext, - reason: BreakpointReason, - ) -> ContinueKind { + pub fn handle_breakpoint(&mut self, _ctx: *mut raw_types::procs::ExecutionContext, reason: BreakpointReason) -> ContinueKind { // Ignore all breakpoints unless we're connected if !self.check_connected() { return ContinueKind::Continue; @@ -1166,10 +1090,7 @@ impl Server { if let BreakpointReason::Breakpoint = reason { let proc = unsafe { (*(*_ctx).proc_instance).proc }; let offset = unsafe { (*_ctx).bytecode_offset }; - let condition = self - .conditional_breakpoints - .get(&(proc, offset)) - .map(|x| x.clone()); + let condition = self.conditional_breakpoints.get(&(proc, offset)).map(|x| x.clone()); if let Some(condition) = condition { if let Some(result) = self.eval_expr(Some(0), &condition) { @@ -1179,7 +1100,8 @@ impl Server { } } - // We might have just executed some code so invalidate the stacks we already fetched + // We might have just executed some code so invalidate the stacks we already + // fetched self.state.as_mut().unwrap().invalidate_stacks(); } } @@ -1196,12 +1118,7 @@ impl Server { } // Hijack eval too so that we can refresh our state after it - if let Request::Eval { - frame_id, - command, - context, - } = request - { + if let Request::Eval { frame_id, command, context } = request { self.handle_eval(frame_id, &command, context); self.state.as_mut().unwrap().invalidate_stacks(); continue; @@ -1232,7 +1149,8 @@ impl Server { should_pause } - /// Block while processing all received requests normally until the debug client is configured + /// Block while processing all received requests normally until the debug + /// client is configured pub fn process_until_configured(&mut self) { self.wait_for_connection(); @@ -1295,11 +1213,7 @@ impl Drop for Server { } impl ServerThread { - fn spawn_listener( - self, - listener: TcpListener, - connection_sender: mpsc::Sender, - ) -> JoinHandle<()> { + fn spawn_listener(self, listener: TcpListener, connection_sender: mpsc::Sender) -> JoinHandle<()> { thread::spawn(move || match listener.accept() { Ok((stream, _)) => { match connection_sender.send(stream.try_clone().unwrap()) { diff --git a/debug_server/src/server_types.rs b/debug_server/src/server_types.rs index 14a4f2c4..8e9757e3 100644 --- a/debug_server/src/server_types.rs +++ b/debug_server/src/server_types.rs @@ -14,45 +14,45 @@ pub enum Request { Eval { frame_id: Option, command: String, - context: Option, + context: Option }, CurrentInstruction { - frame_id: u32, + frame_id: u32 }, BreakpointSet { instruction: InstructionRef, - condition: Option, + condition: Option }, BreakpointUnset { - instruction: InstructionRef, + instruction: InstructionRef }, CatchRuntimes { - should_catch: bool, + should_catch: bool }, LineNumber { proc: ProcRef, - offset: u32, + offset: u32 }, Offset { proc: ProcRef, - line: u32, + line: u32 }, Stacks, StackFrames { stack_id: u32, start_frame: Option, - count: Option, + count: Option }, Scopes { - frame_id: u32, + frame_id: u32 }, Variables { - vars: VariablesRef, + vars: VariablesRef }, Continue { - kind: ContinueKind, + kind: ContinueKind }, - Pause, + Pause } // Message from server -> client @@ -63,54 +63,54 @@ pub enum Response { Eval(EvalResponse), CurrentInstruction(Option), BreakpointSet { - result: BreakpointSetResult, + result: BreakpointSetResult }, BreakpointUnset { - success: bool, + success: bool }, LineNumber { - line: Option, + line: Option }, Offset { - offset: Option, + offset: Option }, Stacks { - stacks: Vec, + stacks: Vec }, StackFrames { frames: Vec, - total_count: u32, + total_count: u32 }, Scopes { arguments: Option, locals: Option, - globals: Option, + globals: Option }, Variables { - vars: Vec, + vars: Vec }, // These responses can occur at any moment, even between a request and its response // I guess they aren't really responses... Disconnect, Notification { - message: String, + message: String }, BreakpointHit { - reason: BreakpointReason, - }, + reason: BreakpointReason + } } #[derive(Serialize, Deserialize, Debug, Hash, PartialEq, Eq, Clone)] pub struct ProcRef { pub path: String, - pub override_id: u32, + pub override_id: u32 } #[derive(Serialize, Deserialize, Debug, Hash, PartialEq, Eq, Clone)] pub struct InstructionRef { pub proc: ProcRef, - pub offset: u32, + pub offset: u32 } #[derive(Serialize, Deserialize, Debug)] @@ -118,7 +118,7 @@ pub enum BreakpointReason { Breakpoint, Step, Pause, - Runtime(String), + Runtime(String) } #[derive(Serialize, Deserialize, Debug)] @@ -126,26 +126,26 @@ pub enum ContinueKind { Continue, StepOver { stack_id: u32 }, StepInto { stack_id: u32 }, - StepOut { stack_id: u32 }, + StepOut { stack_id: u32 } } #[derive(Serialize, Deserialize, Debug)] pub struct Stack { pub id: u32, - pub name: String, + pub name: String } #[derive(Serialize, Deserialize, Debug)] pub struct StackFrame { pub id: u32, pub instruction: InstructionRef, - pub line: Option, + pub line: Option } #[derive(Serialize, Deserialize, Debug, Clone)] pub enum BreakpointSetResult { Success { line: Option }, - Failed, + Failed } #[derive(Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Debug)] @@ -155,11 +155,11 @@ pub struct VariablesRef(pub i32); pub struct Variable { pub name: String, pub value: String, - pub variables: Option, + pub variables: Option } #[derive(Serialize, Deserialize, Debug)] pub struct EvalResponse { pub value: String, - pub variables: Option, + pub variables: Option } diff --git a/debug_server/src/stddef.rs b/debug_server/src/stddef.rs index 7be6c6fa..1cc95143 100644 --- a/debug_server/src/stddef.rs +++ b/debug_server/src/stddef.rs @@ -1,5 +1,7 @@ -use std::ffi::{c_void, CStr, CString}; -use std::os::raw::c_char; +use std::{ + ffi::{c_void, CStr, CString}, + os::raw::c_char +}; use auxtools::*; @@ -26,8 +28,7 @@ fn stddef_init() -> Result<(), String> { return Err("Couldn't get module handle for BYONDCORE".into()); } - let symbol = - libloaderapi::GetProcAddress(module, STDDEF_FN_SYMBOL.as_ptr() as *const c_char); + let symbol = libloaderapi::GetProcAddress(module, STDDEF_FN_SYMBOL.as_ptr() as *const c_char); if symbol.is_null() { return Err("Couldn't find STDDEF_FN in BYONDCORE".into()); } diff --git a/instruction_hooking/Cargo.toml b/instruction_hooking/Cargo.toml index b5696bb1..079b21e5 100644 --- a/instruction_hooking/Cargo.toml +++ b/instruction_hooking/Cargo.toml @@ -2,8 +2,11 @@ name = "instruction_hooking" version = "1.0.0" authors = ["Sophie Wallace ", "Jordan Dominion "] -edition = "2018" publish = false +edition.workspace = true +rust-version.workspace = true +repository.workspace = true +license.workspace = true [build-dependencies] cc = "1.0" diff --git a/instruction_hooking/build.rs b/instruction_hooking/build.rs index 0bacedcd..25b92d5c 100644 --- a/instruction_hooking/build.rs +++ b/instruction_hooking/build.rs @@ -11,16 +11,15 @@ fn main() { "windows" => match env::var("CARGO_CFG_TARGET_ENV").unwrap().as_str() { "gnu" => { build.file("src/execute_instruction_hook.windows.S"); + build.file("src/514/execute_instruction_hook.windows.S"); } "msvc" => { build.file("src/execute_instruction_hook.windows.asm"); + build.file("src/514/execute_instruction_hook.windows.asm"); } - other => panic!( - "don't know how to build hook for family=\"windows\", env={:?}", - other - ), + other => panic!("don't know how to build hook for family=\"windows\", env={:?}", other) }, - other => panic!("don't know how to build hook for family={:?}", other), + other => panic!("don't know how to build hook for family={:?}", other) } build.compile("instruction-hooking-cpp"); diff --git a/instruction_hooking/src/514/execute_instruction_hook.windows.S b/instruction_hooking/src/514/execute_instruction_hook.windows.S new file mode 100644 index 00000000..f4fc865d --- /dev/null +++ b/instruction_hooking/src/514/execute_instruction_hook.windows.S @@ -0,0 +1,20 @@ +// for i686-pc-windows-gnu +.intel_syntax noprefix +.global _execute_instruction_hook +.extern _execute_instruction_original +.extern _handle_instruction + +// EAX = [CURRENT_EXECUTION_CONTEXT] +_execute_instruction_hook_514: + // Give rust a chance to handle the instruction. Leaves [CURRENT_EXECUTION_CONTEXT] in EAX. + PUSH ECX + PUSH EDX + PUSH EAX + call _handle_instruction + ADD ESP, 0x04 + POP EDX + POP ECX + + // Jump to BYOND's default do_instruction. + MOV ECX, _execute_instruction_original + JMP ECX diff --git a/instruction_hooking/src/514/execute_instruction_hook.windows.asm b/instruction_hooking/src/514/execute_instruction_hook.windows.asm new file mode 100644 index 00000000..1584b7c2 --- /dev/null +++ b/instruction_hooking/src/514/execute_instruction_hook.windows.asm @@ -0,0 +1,22 @@ +; for i686-pc-windows-msvc +.MODEL FLAT, C +.CODE + +EXTERN execute_instruction_original : PTR +handle_instruction PROTO, opcode: DWORD + +; EAX = [CURRENT_EXECUTION_CONTEXT] +execute_instruction_hook_514 PROC PUBLIC + ; Give rust a chance to handle the instruction. Leaves [CURRENT_EXECUTION_CONTEXT] in EAX. + PUSH ECX + PUSH EDX + INVOKE handle_instruction, EAX + POP EDX + POP ECX + + ; Jump to BYOND's default do_instruction. + MOV ECX, execute_instruction_original + JMP ECX +execute_instruction_hook_514 ENDP + +END diff --git a/instruction_hooking/src/disassemble_env.rs b/instruction_hooking/src/disassemble_env.rs index 5df79b35..536724d5 100644 --- a/instruction_hooking/src/disassemble_env.rs +++ b/instruction_hooking/src/disassemble_env.rs @@ -5,23 +5,11 @@ pub struct DisassembleEnv; impl dmasm::disassembler::DisassembleEnv for DisassembleEnv { fn get_string_data(&mut self, index: u32) -> Option> { - unsafe { - Some( - StringRef::from_id(raw_types::strings::StringId(index)) - .data() - .to_vec(), - ) - } + unsafe { Some(StringRef::from_id(raw_types::strings::StringId(index)).data().to_vec()) } } fn get_variable_name(&mut self, index: u32) -> Option> { - unsafe { - Some( - StringRef::from_variable_id(raw_types::strings::VariableId(index)) - .data() - .to_vec(), - ) - } + unsafe { Some(StringRef::from_variable_id(raw_types::strings::VariableId(index)).data().to_vec()) } } fn get_proc_name(&mut self, index: u32) -> Option { @@ -33,7 +21,7 @@ impl dmasm::disassembler::DisassembleEnv for DisassembleEnv { let value = Value::new(std::mem::transmute(tag as u8), std::mem::transmute(data)); match value.to_dmstring() { Ok(s) => Some(s.data().to_vec()), - _ => None, + _ => None } } } diff --git a/instruction_hooking/src/lib.rs b/instruction_hooking/src/lib.rs index 24228df4..72e8ca41 100644 --- a/instruction_hooking/src/lib.rs +++ b/instruction_hooking/src/lib.rs @@ -1,18 +1,24 @@ pub mod disassemble_env; -use std::{any::Any, cell::UnsafeCell, ffi::c_void}; - use auxtools::*; use detour::RawDetour; +use std::{any::Any, cell::UnsafeCell, ffi::c_void}; #[cfg(windows)] signatures! { - execute_instruction => universal_signature!("0F B7 47 ?? 8B 4F ?? 8B F0 8B 14 ?? 89 95 ?? ?? ?? ?? 81 FA 78 01 00 00") + execute_instruction => version_dependent_signature!( + 1616.. => "0F B7 47 ?? 8B 4F ?? 8B F0 8B 14 ?? 89 95 ?? ?? ?? ?? 81 FA 78 01 00 00", + 1590..1616 => "0F B7 48 ?? 8B ?? ?? 8B F1 8B ?? ?? 81 ?? ?? ?? 00 00 0F 87 ?? ?? ?? ??", + ..1590 => "0F B7 48 ?? 8B 78 ?? 8B F1 8B 14 ?? 81 FA ?? ?? 00 00 0F 87 ?? ?? ?? ??" + ) } #[cfg(unix)] signatures! { - execute_instruction => universal_signature!("0F B7 C0 8D 14 ?? 8B 02 8B 52 ?? 8B 4E ?? 8B 5E ?? 89 46 ?? 89 56 ?? 89 0C 24") + execute_instruction => version_dependent_signature!( + 1616.. => "0F B7 C0 8D 14 ?? 8B 02 8B 52 ?? 8B 4E ?? 8B 5E ?? 89 46 ?? 89 56 ?? 89 0C 24", + ..1616 => "0F B7 47 ?? 8B 57 ?? 0F B7 D8 8B 0C ?? 81 F9 ?? ?? 00 00 77 ?? FF 24 8D ?? ?? ?? ??" + ) } // stackoverflow copypasta https://old.reddit.com/r/rust/comments/kkap4e/how_to_cast_a_boxdyn_mytrait_to_an_actual_struct/ @@ -30,15 +36,18 @@ pub trait InstructionHook: InstructionHookToAny { fn handle_instruction(&mut self, ctx: *mut raw_types::procs::ExecutionContext); } -pub static mut INSTRUCTION_HOOKS: UnsafeCell>> = - UnsafeCell::new(Vec::new()); +pub static mut INSTRUCTION_HOOKS: UnsafeCell>> = UnsafeCell::new(Vec::new()); extern "C" { // Trampoline to the original un-hooked BYOND execute_instruction code static mut execute_instruction_original: *const c_void; - // Our version of execute_instruction. It hasn't got a calling convention rust knows about, so don't call it. + // Our version of execute_instruction. It hasn't got a calling convention rust + // knows about, so don't call it. fn execute_instruction_hook(); + + // The 514 version of the instruction hook. + fn execute_instruction_hook_514(); } #[init(full)] @@ -49,15 +58,16 @@ fn instruction_hooking_init() -> Result<(), String> { execute_instruction } + let versioned_hook = if cfg!(windows) && auxtools::version::get().0 == 514 { + execute_instruction_hook_514 as *const () + } else { + execute_instruction_hook as *const () + }; + unsafe { - let hook = RawDetour::new( - execute_instruction as *const (), - execute_instruction_hook as *const (), - ) - .map_err(|_| "Couldn't detour execute_instruction")?; + let hook = RawDetour::new(execute_instruction as *const (), versioned_hook).map_err(|_| "Couldn't detour execute_instruction")?; - hook.enable() - .map_err(|_| "Couldn't enable execute_instruction detour")?; + hook.enable().map_err(|_| "Couldn't enable execute_instruction detour")?; execute_instruction_original = std::mem::transmute(hook.trampoline()); @@ -76,11 +86,10 @@ fn instruction_hooking_shutdown() { } // Handles any instruction BYOND tries to execute. -// This function has to leave `*CURRENT_EXECUTION_CONTEXT` in EAX, so make sure to return it. +// This function has to leave `*CURRENT_EXECUTION_CONTEXT` in EAX, so make sure +// to return it. #[no_mangle] -extern "C" fn handle_instruction( - ctx: *mut raw_types::procs::ExecutionContext, -) -> *const raw_types::procs::ExecutionContext { +extern "C" fn handle_instruction(ctx: *mut raw_types::procs::ExecutionContext) -> *const raw_types::procs::ExecutionContext { unsafe { for vec_box in &mut *INSTRUCTION_HOOKS.get() { vec_box.handle_instruction(ctx); diff --git a/tests/auxtest/src/strings.rs b/tests/auxtest/src/strings.rs index ae92bd72..fc5ca5f3 100644 --- a/tests/auxtest/src/strings.rs +++ b/tests/auxtest/src/strings.rs @@ -1,11 +1,10 @@ -use auxtools::*; use std::ffi::CString; +use auxtools::*; + #[hook("/proc/auxtest_strings")] fn test_strings() { - use raw_types::funcs; - use raw_types::strings; - use raw_types::values; + use raw_types::{funcs, strings, values}; unsafe { let string_a_contents = CString::new("relatively unique testing string").unwrap(); @@ -16,22 +15,10 @@ fn test_strings() { let mut string_a_entry: *mut strings::StringEntry = std::ptr::null_mut(); let mut string_b_entry: *mut strings::StringEntry = std::ptr::null_mut(); { - assert_eq!( - funcs::get_string_id(&mut string_a, string_a_contents.as_ptr()), - 1 - ); - assert_eq!( - funcs::get_string_id(&mut string_b, string_b_contents.as_ptr()), - 1 - ); - assert_eq!( - funcs::get_string_table_entry(&mut string_a_entry, string_a), - 1 - ); - assert_eq!( - funcs::get_string_table_entry(&mut string_b_entry, string_b), - 1 - ); + assert_eq!(funcs::get_string_id(&mut string_a, string_a_contents.as_ptr()), 1); + assert_eq!(funcs::get_string_id(&mut string_b, string_b_contents.as_ptr()), 1); + assert_eq!(funcs::get_string_table_entry(&mut string_a_entry, string_a), 1); + assert_eq!(funcs::get_string_table_entry(&mut string_b_entry, string_b), 1); } // New strings should start with a reference count of 0. @@ -43,75 +30,50 @@ fn test_strings() { return Err(runtime!("test_string: string_a's reference count != 0")); } - // Creating a value from our strings should result in both having a reference count of 1. - let value_a = Value::new( - values::ValueTag::String, - values::ValueData { string: string_a }, - ); + // Creating a value from our strings should result in both having a reference + // count of 1. + let value_a = Value::new(values::ValueTag::String, values::ValueData { string: string_a }); - let value_b = Value::new( - values::ValueTag::String, - values::ValueData { string: string_b }, - ); + let value_b = Value::new(values::ValueTag::String, values::ValueData { string: string_b }); if (*string_a_entry).ref_count != 1 { - return Err(runtime!( - "test_string: string_a's reference count != 1 after Value::new" - )); + return Err(runtime!("test_string: string_a's reference count != 1 after Value::new")); } if (*string_b_entry).ref_count != 1 { - return Err(runtime!( - "test_string: string_a's reference count != 1 after Value::new" - )); + return Err(runtime!("test_string: string_a's reference count != 1 after Value::new")); } - let concatenated = Proc::find("/proc/concat_strings") - .unwrap() - .call(&[&value_a, &value_b])?; + let concatenated = Proc::find("/proc/concat_strings").unwrap().call(&[&value_a, &value_b])?; // Returned value should be equal to string_a_contents .. string_b_contents // and have a ref count of 1 if concatenated.raw.tag != values::ValueTag::String { - return Err(runtime!( - "test_string: concat_strings did not return a string" - )); + return Err(runtime!("test_string: concat_strings did not return a string")); } let mut concatenated_entry: *mut strings::StringEntry = std::ptr::null_mut(); - assert_eq!( - funcs::get_string_table_entry(&mut concatenated_entry, concatenated.raw.data.string), - 1 - ); + assert_eq!(funcs::get_string_table_entry(&mut concatenated_entry, concatenated.raw.data.string), 1); if (*concatenated_entry).ref_count != 1 { - return Err(runtime!( - "test_string: concatenated's reference count != 1 after concat_strings()" - )); + return Err(runtime!("test_string: concatenated's reference count != 1 after concat_strings()")); } - let expected_concat = format!( - "{}{}", - string_a_contents.to_str().unwrap(), - string_b_contents.to_str().unwrap() - ); + let expected_concat = format!("{}{}", string_a_contents.to_str().unwrap(), string_b_contents.to_str().unwrap()); let actual_concat = concatenated.as_string()?; if actual_concat != expected_concat { return Err(runtime!("test_string: expected_concat != actual_concat")); } - // The strings should still have a reference count of 1 after concat_strings has used them + // The strings should still have a reference count of 1 after concat_strings has + // used them if (*string_a_entry).ref_count != 1 { - return Err(runtime!( - "test_string: string_a's reference count != 1 after concat_strings" - )); + return Err(runtime!("test_string: string_a's reference count != 1 after concat_strings")); } if (*string_b_entry).ref_count != 1 { - return Err(runtime!( - "test_string: string_a's reference count != 1 after concat_strings" - )); + return Err(runtime!("test_string: string_a's reference count != 1 after concat_strings")); } Ok(Value::from(true)) diff --git a/tests/auxtest/src/value_from.rs b/tests/auxtest/src/value_from.rs index 6b881995..95cef9b5 100644 --- a/tests/auxtest/src/value_from.rs +++ b/tests/auxtest/src/value_from.rs @@ -1,25 +1,23 @@ +use std::{collections::HashMap, convert::TryFrom}; + use auxtools::*; -use std::collections::HashMap; -use std::convert::TryFrom; #[hook("/proc/auxtest_value_from")] fn test_value_from() { - /* Numbers */ + // Numbers let value = Value::from(30); if value.as_number()? != 30.0 { return Err(runtime!("value_from: Value failed to convert i32")); } - /* Vectors */ + // Vectors // The simplest case: A Vec of Value's. let mut vector: Vec = Vec::new(); vector.push(5.into()); let value = Value::from(&vector); let list = List::from_value(&value)?; if list.len() != 1 { - return Err(runtime!( - "value_from: Vec with one entry did not result in a list length of one" - )); + return Err(runtime!("value_from: Vec with one entry did not result in a list length of one")); } let value = list.get(1)?.as_number()?; if value != 5.0 { @@ -29,7 +27,7 @@ fn test_value_from() { )); }; - /* Hashmaps */ + // Hashmaps // The simplest case: Value -> Value let mut hashmap: HashMap = HashMap::new(); hashmap.insert(Value::from_string("meow")?, 1.into()); @@ -42,7 +40,7 @@ fn test_value_from() { let value = Value::try_from(&hashmap)?; assert_meow_equals_one(value)?; - /* Todo: Other stuff */ + // Todo: Other stuff Ok(Value::from(true)) } @@ -61,9 +59,7 @@ fn assert_meow_equals_one(value: Value) -> Result<(), Runtime> { let list = List::from_value(&value)?; if list.len() != 1 { - return Err(runtime!( - "value_from: Hashmap with one key did not result in a list length of one" - )); + return Err(runtime!("value_from: Hashmap with one key did not result in a list length of one")); } let value = list.get(byond_string!("meow"))?.as_number()?; diff --git a/tests/auxtest/src/weak.rs b/tests/auxtest/src/weak.rs index ba011c75..2a2a64b7 100644 --- a/tests/auxtest/src/weak.rs +++ b/tests/auxtest/src/weak.rs @@ -5,9 +5,7 @@ fn test_weak_values(someval: Value) { let weak = someval.as_weak()?; if weak.upgrade().is_none() { - return Err(runtime!( - "test_weak_values: Failed to upgrade weak reference to existing value" - )); + return Err(runtime!("test_weak_values: Failed to upgrade weak reference to existing value")); } Proc::find("/proc/del_value") @@ -19,9 +17,7 @@ fn test_weak_values(someval: Value) { .call(&[])?; if weak.upgrade().is_some() { - return Err(runtime!( - "test_weak_values: Upgraded a weak reference to deleted value" - )); + return Err(runtime!("test_weak_values: Upgraded a weak reference to deleted value")); } Ok(Value::from(true)) diff --git a/tests/byond_get/src/main.rs b/tests/byond_get/src/main.rs index 3bdbad62..d145ce98 100644 --- a/tests/byond_get/src/main.rs +++ b/tests/byond_get/src/main.rs @@ -3,11 +3,7 @@ use std::{fs, path::Path}; use clap::{Arg, Command}; fn get_zip_url(major: u32, minor: u32) -> reqwest::Url { - reqwest::Url::parse(&format!( - "https://secure.byond.com/download/build/{0}/{0}.{1}_byond.zip", - major, minor - )) - .unwrap() + reqwest::Url::parse(&format!("https://secure.byond.com/download/build/{0}/{0}.{1}_byond.zip", major, minor)).unwrap() } fn main() { @@ -17,20 +13,20 @@ fn main() { Arg::new("major") .help("major BYOND version to fetch (e.g. 513)") .required(true) - .takes_value(true), + .takes_value(true) ) .arg( Arg::new("minor") .help("minor BYOND version to fetch (e.g. 1539)") .required(true) - .takes_value(true), + .takes_value(true) ) .arg( Arg::new("destination") .allow_invalid_utf8(true) .help("directory to extract the BYOND build into") .required(true) - .takes_value(true), + .takes_value(true) ) .get_matches(); @@ -38,22 +34,15 @@ fn main() { let minor = matches.value_of("minor").unwrap(); let destination = matches.value_of_os("destination").unwrap(); - let major = major - .parse::() - .expect("major version must be an integer"); - let minor = minor - .parse::() - .expect("minor version must be an integer"); + let major = major.parse::().expect("major version must be an integer"); + let minor = minor.parse::().expect("minor version must be an integer"); let destination = Path::new(destination); if destination.exists() { panic!("path {:?} already exists", destination); } - let resp = reqwest::blocking::get(get_zip_url(major, minor)) - .unwrap() - .bytes() - .unwrap(); + let resp = reqwest::blocking::get(get_zip_url(major, minor)).unwrap().bytes().unwrap(); let stream = std::io::Cursor::new(resp); let mut archive = zip::ZipArchive::new(stream).unwrap(); @@ -64,11 +53,7 @@ fn main() { continue; } - let local_path = file - .enclosed_name() - .unwrap() - .strip_prefix("byond/") - .unwrap(); + let local_path = file.enclosed_name().unwrap().strip_prefix("byond/").unwrap(); let mut path = destination.to_path_buf(); path.push(local_path); diff --git a/tests/test_runner/src/main.rs b/tests/test_runner/src/main.rs index e1b62469..813bd232 100644 --- a/tests/test_runner/src/main.rs +++ b/tests/test_runner/src/main.rs @@ -22,10 +22,7 @@ impl ByondCommand for Command { let ld_library_path = format!( "{}:{}", byond_bin.as_os_str().to_str().unwrap(), - std::env::var_os("LD_LIBRARY_PATH") - .unwrap() - .to_str() - .unwrap() + std::env::var_os("LD_LIBRARY_PATH").unwrap().to_str().unwrap() ); self.env("BYOND_SYSTEM", byond_system) @@ -42,14 +39,11 @@ impl ByondCommand for Command { } fn main() { - let res = Command::new(paths::find_dm()) - .with_byond_paths() - .arg(paths::find_dme()) - .status() - .unwrap(); + let res = Command::new(paths::find_dm()).with_byond_paths().arg(paths::find_dme()).status().unwrap(); assert!(res.success(), "dreamdaemon build failed"); - // Here we depend on BYOND not fucking with stderr too much so we can hijack it for our own communication + // Here we depend on BYOND not fucking with stderr too much so we can hijack it + // for our own communication let output = Command::new(paths::find_dreamdaemon()) .with_byond_paths() .env("AUXTEST_DLL", paths::find_dll()) @@ -63,20 +57,14 @@ fn main() { let res = std::str::from_utf8(&output).unwrap(); // Check for any messages matching "FAILED: " - let errors = res - .lines() - .filter(|x| x.starts_with("FAILED: ")) - .collect::>(); + let errors = res.lines().filter(|x| x.starts_with("FAILED: ")).collect::>(); if !errors.is_empty() { panic!("TESTS FAILED\n{}", errors.join("\n")); } // Now make sure we have only one message matching "SUCCESS: " - let successes = res - .lines() - .filter(|x| x.starts_with("SUCCESS: ")) - .collect::>(); + let successes = res.lines().filter(|x| x.starts_with("SUCCESS: ")).collect::>(); assert_eq!(successes.len(), 1, "Tests didn't output success message"); println!("Tests Succeeded");