From c8b69249b113837f67012f186aa27dfd692434c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=BCller?= Date: Mon, 10 Feb 2025 14:34:35 -0800 Subject: [PATCH] capi: XXX --- capi/src/symbolize.rs | 90 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/capi/src/symbolize.rs b/capi/src/symbolize.rs index 21a691ef..bf1af9cb 100644 --- a/capi/src/symbolize.rs +++ b/capi/src/symbolize.rs @@ -12,6 +12,7 @@ use std::path::Path; use std::path::PathBuf; use std::ptr; +use blazesym::symbolize::cache; use blazesym::symbolize::source::Elf; use blazesym::symbolize::source::GsymData; use blazesym::symbolize::source::GsymFile; @@ -36,6 +37,58 @@ use crate::util::slice_from_aligned_user_array; use crate::util::slice_from_user_array; +/// Configuration for caching of process-level data. +#[repr(C)] +#[derive(Debug)] +pub struct blaze_symbolize_cache_process { + /// The size of this object's type. + /// + /// Make sure to initialize it to `sizeof()`. This member is used to + /// ensure compatibility in the presence of member additions. + pub type_size: usize, + /// The referenced process' ID. + pub pid: u32, + /// Whether to cache the process' VMAs for later use. + /// + /// Caching VMAs can be useful, because it conceptually enables the + /// library to serve a symbolization request targeting a process + /// even if said process has since exited the system. + /// + /// Note that once VMAs have been cached this way, the library will + /// refrain from re-reading updated VMAs unless instructed to. + /// Hence, if you have reason to believe that a process may have + /// changed its memory regions (by loading a new shared object, for + /// example), you would have to make another request to cache them + /// yourself. + /// + /// Note furthermore that if you cache VMAs to later symbolize + /// addresses after the original process has already exited, you + /// will have to opt-out of usage of `/proc//map_files/` as + /// part of the symbolization request. Refer to + /// [`source::Process::map_files`][crate::symbolize::source::Process::map_files]. + pub cache_vmas: bool, + /// Unused member available for future expansion. Must be initialized + /// to zero. + pub reserved: [u8; 15], +} + +impl From for cache::Process { + fn from(elf: blaze_symbolize_cache_process) -> Self { + let blaze_symbolize_cache_process { + type_size: _, + pid, + cache_vmas, + reserved: _, + } = elf; + Self { + pid: pid.into(), + cache_vmas, + _non_exhaustive: (), + } + } +} + + /// The parameters to load symbols and debug information from an ELF. /// /// Describes the path and address of an ELF file loaded in a @@ -689,6 +742,43 @@ pub unsafe extern "C" fn blaze_symbolizer_free(symbolizer: *mut blaze_symbolizer } } + +/// Symbolize a list of process absolute addresses. +/// +/// On success, the function returns a [`blaze_syms`] containing an +/// array of `abs_addr_cnt` [`blaze_sym`] objects. The returned object +/// should be released using [`blaze_syms_free`] once it is no longer +/// needed. +/// +/// On error, the function returns `NULL` and sets the thread's last error to +/// indicate the problem encountered. Use [`blaze_err_last`] to retrieve this +/// error. +/// +/// # Safety +/// - `symbolizer` needs to point to a valid [`blaze_symbolizer`] object +/// - `src` needs to point to a valid [`blaze_symbolize_src_process`] object +/// - `abs_addrs` point to an array of `abs_addr_cnt` addresses +#[no_mangle] +pub unsafe extern "C" fn blaze_symbolize_cache_process( + symbolizer: *mut blaze_symbolizer, + cache: *const blaze_symbolize_cache_process, +) { + if !input_zeroed!(cache, blaze_symbolize_cache_process) { + let () = set_last_err(blaze_err::BLAZE_ERR_INVALID_INPUT); + return + } + let cache = input_sanitize!(cache, blaze_symbolize_cache_process); + let cache = cache::Cache::from(cache::Process::from(cache)); + + // SAFETY: The caller ensures that the pointer is valid. + let symbolizer = unsafe { &*symbolizer }; + let result = symbolizer.cache(&cache); + let err = result + .map(|()| blaze_err::BLAZE_ERR_OK) + .unwrap_or_else(|err| err.kind().into()); + let () = set_last_err(err); +} + fn code_info_strtab_size(code_info: &Option) -> usize { code_info .as_ref()