subsecond_types/
lib.rs

1use serde::{Deserialize, Serialize};
2use std::{
3    collections::HashMap,
4    hash::{BuildHasherDefault, Hasher},
5    path::PathBuf,
6};
7
8#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
9pub struct JumpTable {
10    /// The dylib containing the patch. This should be a valid path so you can just pass it to LibLoading
11    ///
12    /// On wasm you will need to fetch() this file and then pass it to the WebAssembly.instantiate() function
13    pub lib: PathBuf,
14
15    /// old -> new
16    /// does not take into account the base address of the patch when loaded into memory - need dlopen for that
17    ///
18    /// These are intended to be `*const ()` pointers but need to be `u64` for the hashmap. On 32-bit platforms
19    /// you will need to cast to `usize` before using them.
20    pub map: AddressMap,
21
22    /// the address of the base address of the old original binary
23    ///
24    /// machos: this is the address of the `_mh_execute_header` symbol usually at 0x100000000 and loaded near 0x100000000
25    /// linux: this is the address of the `__executable_start` symbol usually at 0x0 but loaded around 0x555555550000
26    /// windows: this is the address of the `ImageBase` field of the PE header
27    /// wasm: not useful since there's no ASLR
28    ///
29    /// While we can generally guess that these values are, it's possible they are different and thus reading
30    /// them dynamically is worthwhile.
31    pub aslr_reference: u64,
32
33    /// the address of the base address of the new binary
34    ///
35    /// machos: this is the address of the `_mh_execute_header` symbol usually at 0x100000000 and loaded near 0x100000000
36    /// linux: this is the address of the `__executable_start` symbol usually at 0x0 but loaded around 0x555555550000
37    /// windows: this is the address of the `ImageBase` field of the PE header
38    /// wasm: not useful since there's no ASLR
39    ///
40    /// While we can generally guess that these values are, it's possible they are different and thus reading
41    /// them dynamically is worthwhile.
42    pub new_base_address: u64,
43
44    /// The amount of ifuncs this will register. This is used by WASM to know how much space to allocate
45    /// for the ifuncs in the ifunc table
46    pub ifunc_count: u64,
47}
48
49/// An address to address hashmap that does not hash addresses since addresses are by definition unique.
50pub type AddressMap = HashMap<u64, u64, BuildAddressHasher>;
51pub type BuildAddressHasher = BuildHasherDefault<AddressHasher>;
52
53#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
54pub struct AddressHasher(u64);
55impl Hasher for AddressHasher {
56    fn write(&mut self, _: &[u8]) {
57        panic!("Invalid use of NoHashHasher")
58    }
59    fn write_u8(&mut self, n: u8) {
60        self.0 = u64::from(n)
61    }
62    fn write_u16(&mut self, n: u16) {
63        self.0 = u64::from(n)
64    }
65    fn write_u32(&mut self, n: u32) {
66        self.0 = u64::from(n)
67    }
68    fn write_u64(&mut self, n: u64) {
69        self.0 = n
70    }
71    fn write_usize(&mut self, n: usize) {
72        self.0 = n as u64
73    }
74    fn write_i8(&mut self, n: i8) {
75        self.0 = n as u64
76    }
77    fn write_i16(&mut self, n: i16) {
78        self.0 = n as u64
79    }
80    fn write_i32(&mut self, n: i32) {
81        self.0 = n as u64
82    }
83    fn write_i64(&mut self, n: i64) {
84        self.0 = n as u64
85    }
86    fn write_isize(&mut self, n: isize) {
87        self.0 = n as u64
88    }
89    fn finish(&self) -> u64 {
90        self.0
91    }
92}