#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(feature = "nightly", feature(test))]
#![cfg_attr(
not(all(
feature = "apk",
feature = "bpf",
feature = "breakpad",
feature = "dwarf",
feature = "gsym"
)),
allow(dead_code, unused_imports)
)]
#![cfg_attr(not(linux), allow(dead_code, unused_imports))]
#[cfg(feature = "nightly")]
#[allow(unused_extern_crates)]
extern crate test;
#[macro_use]
mod cfg;
#[cfg(feature = "apk")]
mod apk;
#[cfg(feature = "breakpad")]
mod breakpad;
#[cfg(feature = "dwarf")]
mod dwarf;
mod elf;
mod error;
mod file_cache;
#[cfg(feature = "gsym")]
mod gsym;
mod insert_map;
pub mod inspect;
mod kernel;
mod maps;
mod mmap;
pub mod normalize;
mod pathlike;
mod perf_map;
mod pid;
pub mod symbolize;
#[cfg(any(test, feature = "test"))]
mod test_helper;
mod util;
mod vdso;
#[cfg(feature = "apk")]
mod zip;
use std::result;
pub use crate::error::Error;
pub use crate::error::ErrorExt;
pub use crate::error::ErrorKind;
pub use crate::error::IntoError;
pub use crate::mmap::Mmap;
pub use crate::normalize::buildid::BuildId;
pub use crate::pid::Pid;
pub type Result<T, E = Error> = result::Result<T, E>;
pub type Addr = u64;
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
#[non_exhaustive]
pub enum SymType {
#[default]
Undefined,
Function,
Variable,
}
#[derive(Clone, Debug, PartialEq)]
pub enum MaybeDefault<T> {
None,
Default,
Some(T),
}
impl<T> From<T> for MaybeDefault<T> {
#[inline]
fn from(value: T) -> Self {
Self::Some(value)
}
}
pub mod helper {
use super::Addr;
use super::Result;
pub use crate::normalize::buildid::read_elf_build_id;
pub use crate::normalize::buildid::read_elf_build_id_from_mmap;
pub use crate::normalize::ioctl::is_procmap_query_supported;
cfg_breakpad! {
pub use crate::breakpad::BreakpadResolver;
}
pub use crate::elf::ElfResolver;
cfg_gsym! {
use std::path::Path;
use crate::symbolize::Symbolize;
use crate::symbolize::ResolvedSym;
use crate::symbolize::Reason;
use crate::symbolize::FindSymOpts;
use crate::gsym;
#[derive(Debug)]
pub struct GsymResolver(gsym::GsymResolver<'static>);
impl GsymResolver {
#[inline]
pub fn open<P>(path: P) -> Result<Self>
where
P: AsRef<Path>,
{
Ok(Self(gsym::GsymResolver::open(path)?))
}
}
impl Symbolize for GsymResolver {
#[inline]
fn find_sym(&self, addr: Addr, opts: &FindSymOpts) -> Result<Result<ResolvedSym<'_>, Reason>> {
self.0.find_sym(addr, opts)
}
}
}
}
#[doc(hidden)]
pub mod __private {
pub use crate::util::bytes_to_path;
pub use crate::util::stat;
pub use crate::util::ReadRaw;
#[cfg(feature = "apk")]
pub mod zip {
pub use crate::zip::Archive;
}
#[cfg(linux)]
#[cfg(feature = "test")]
pub use crate::test_helper::find_gettimeofday_in_process;
#[cfg(feature = "test")]
pub use crate::test_helper::find_the_answer_fn;
#[cfg(feature = "test")]
pub use crate::test_helper::find_the_answer_fn_in_zip;
#[cfg(linux)]
#[cfg(feature = "test")]
pub use crate::test_helper::find_vdso_range;
}
#[cfg(feature = "tracing")]
#[macro_use]
#[allow(unused_imports)]
mod log {
pub(crate) use tracing::debug;
pub(crate) use tracing::error;
pub(crate) use tracing::info;
pub(crate) use tracing::instrument;
pub(crate) use tracing::trace;
pub(crate) use tracing::warn;
}
#[cfg(not(feature = "tracing"))]
#[macro_use]
#[allow(unused_imports)]
mod log {
macro_rules! debug {
($($args:tt)*) => {{
if false {
let _args = format_args!($($args)*);
}
}};
}
pub(crate) use debug;
pub(crate) use debug as error;
pub(crate) use debug as info;
pub(crate) use debug as trace;
pub(crate) use debug as warn;
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::Path;
use crate::symbolize::FindSymOpts;
use crate::symbolize::Symbolize as _;
#[test]
fn gsym_resolver() {
let test_gsym = Path::new(&env!("CARGO_MANIFEST_DIR"))
.join("data")
.join("test-stable-addrs.gsym");
let resolver = helper::GsymResolver::open(test_gsym).unwrap();
let sym = resolver
.find_sym(0x2000200, &FindSymOpts::Basic)
.unwrap()
.unwrap();
assert_eq!(sym.name, "factorial");
}
}