Skip to content

Commit

Permalink
Add process_get_module_path (#735)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexKnauth authored Nov 1, 2023
1 parent 0ccaa66 commit ee71245
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 0 deletions.
17 changes: 17 additions & 0 deletions crates/livesplit-auto-splitting/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,23 @@ extern "C" {
name_ptr: *const u8,
name_len: usize,
) -> Option<NonZeroU64>;
/// Stores the file system path of a module in a process in the buffer
/// given. The pointer to the module name needs to point to valid UTF-8
/// encoded text with the given length. The path is a path that is
/// accessible through the WASI file system, so a Windows path of
/// `C:\foo\bar.exe` would be returned as `/mnt/c/foo/bar.exe`. Returns
/// `false` if the buffer is too small. After this call, no matter whether
/// it was successful or not, the `buf_len_ptr` will be set to the required
/// buffer size. If `false` is returned and the `buf_len_ptr` got set to 0,
/// the path or the module does not exist or it failed to get read. The path
/// is guaranteed to be valid UTF-8 and is not nul-terminated.
pub fn process_get_module_path(
process: Process,
name_ptr: *const u8,
name_len: usize,
buf_ptr: *mut u8,
buf_len_ptr: *mut usize,
) -> bool;
/// Stores the file system path of the executable in the buffer given. The
/// path is a path that is accessible through the WASI file system, so a
/// Windows path of `C:\foo\bar.exe` would be returned as
Expand Down
17 changes: 17 additions & 0 deletions crates/livesplit-auto-splitting/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,23 @@
//! name_ptr: *const u8,
//! name_len: usize,
//! ) -> Option<NonZeroU64>;
//! /// Stores the file system path of a module in a process in the buffer
//! /// given. The pointer to the module name needs to point to valid UTF-8
//! /// encoded text with the given length. The path is a path that is
//! /// accessible through the WASI file system, so a Windows path of
//! /// `C:\foo\bar.exe` would be returned as `/mnt/c/foo/bar.exe`. Returns
//! /// `false` if the buffer is too small. After this call, no matter whether
//! /// it was successful or not, the `buf_len_ptr` will be set to the required
//! /// buffer size. If `false` is returned and the `buf_len_ptr` got set to 0,
//! /// the path or the module does not exist or it failed to get read. The path
//! /// is guaranteed to be valid UTF-8 and is not nul-terminated.
//! pub fn process_get_module_path(
//! process: Process,
//! name_ptr: *const u8,
//! name_len: usize,
//! buf_ptr: *mut u8,
//! buf_len_ptr: *mut usize,
//! ) -> bool;
//! /// Stores the file system path of the executable in the buffer given. The
//! /// path is a path that is accessible through the WASI file system, so a
//! /// Windows path of `C:\foo\bar.exe` would be returned as
Expand Down
9 changes: 9 additions & 0 deletions crates/livesplit-auto-splitting/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,15 @@ impl Process {
.sum())
}

pub(super) fn module_path(&mut self, module: &str) -> Result<Box<str>, ModuleError> {
self.refresh_memory_ranges()?;
self.memory_ranges
.iter()
.find(|m| m.filename().is_some_and(|f| f.ends_with(module)))
.context(ModuleDoesntExist)
.map(|m| build_path(m.filename().unwrap()).unwrap_or_default())
}

pub(super) fn read_mem(&self, address: Address, buf: &mut [u8]) -> io::Result<()> {
self.handle.copy_address(address as usize, buf)
}
Expand Down
35 changes: 35 additions & 0 deletions crates/livesplit-auto-splitting/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -954,6 +954,41 @@ fn bind_interface<T: Timer>(linker: &mut Linker<Context<T>>) -> Result<(), Creat
source,
name: "process_get_path",
})?
.func_wrap("env", "process_get_module_path", {
|mut caller: Caller<'_, Context<T>>,
process: u64,
name_ptr: u32,
name_len: u32,
path_ptr: u32,
path_len_ptr: u32| {
let (memory, context) = memory_and_context(&mut caller);
let module_name = get_str(memory, name_ptr, name_len)?;
let path = context
.processes
.get_mut(ProcessKey::from(KeyData::from_ffi(process)))
.ok_or_else(|| format_err!("Invalid process handle: {process}"))?
.module_path(module_name);

let path_len_bytes = get_arr_mut(memory, path_len_ptr)?;
if let Ok(path) = path {
let path_len = u32::from_le_bytes(*path_len_bytes) as usize;
*path_len_bytes = (path.len() as u32).to_le_bytes();
if path_len < path.len() {
return Ok(0u32);
}
let buf = get_slice_mut(memory, path_ptr, path.len() as _)?;
buf.copy_from_slice(path.as_bytes());
Ok(1u32)
} else {
*path_len_bytes = 0u32.to_le_bytes();
Ok(0u32)
}
}
})
.map_err(|source| CreationError::LinkFunction {
source,
name: "process_get_module_path",
})?
.func_wrap("env", "process_read", {
|mut caller: Caller<'_, Context<T>>,
process: u64,
Expand Down
17 changes: 17 additions & 0 deletions src/auto_splitting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,23 @@
//! name_ptr: *const u8,
//! name_len: usize,
//! ) -> Option<NonZeroU64>;
//! /// Stores the file system path of a module in a process in the buffer
//! /// given. The pointer to the module name needs to point to valid UTF-8
//! /// encoded text with the given length. The path is a path that is
//! /// accessible through the WASI file system, so a Windows path of
//! /// `C:\foo\bar.exe` would be returned as `/mnt/c/foo/bar.exe`. Returns
//! /// `false` if the buffer is too small. After this call, no matter whether
//! /// it was successful or not, the `buf_len_ptr` will be set to the required
//! /// buffer size. If `false` is returned and the `buf_len_ptr` got set to 0,
//! /// the path or the module does not exist or it failed to get read. The path
//! /// is guaranteed to be valid UTF-8 and is not nul-terminated.
//! pub fn process_get_module_path(
//! process: Process,
//! name_ptr: *const u8,
//! name_len: usize,
//! buf_ptr: *mut u8,
//! buf_len_ptr: *mut usize,
//! ) -> bool;
//! /// Stores the file system path of the executable in the buffer given. The
//! /// path is a path that is accessible through the WASI file system, so a
//! /// Windows path of `C:\foo\bar.exe` would be returned as
Expand Down

0 comments on commit ee71245

Please sign in to comment.