diff --git a/src/symbolize/symbolizer.rs b/src/symbolize/symbolizer.rs index e890f4b4..359985cb 100644 --- a/src/symbolize/symbolizer.rs +++ b/src/symbolize/symbolizer.rs @@ -1565,126 +1565,4 @@ mod tests { syms[0] ); } - - /// Check that we can symbolize an address residing in a zip archive. - #[test] - fn symbolize_zip() { - let test_zip = Path::new(&env!("CARGO_MANIFEST_DIR")) - .join("data") - .join("test.zip"); - - let mmap = Mmap::builder().exec().open(test_zip).unwrap(); - let (sym, the_answer_addr) = find_the_answer_fn_in_zip(&mmap); - - // Symbolize the address we just looked up. It should be correctly - // mapped to the `the_answer` function within our process. - let src = symbolize::Source::Process(symbolize::Process::new(Pid::Slf)); - let symbolizer = Symbolizer::new(); - let result = symbolizer - .symbolize_single(&src, Input::AbsAddr(the_answer_addr)) - .unwrap() - .into_sym() - .unwrap(); - - assert_eq!(result.name, "the_answer"); - assert_eq!(result.addr, sym.addr); - } - - /// Check that we can symbolize an address residing in a zip archive, using - /// a custom APK dispatcher. - #[test] - fn symbolize_zip_with_custom_dispatch() { - fn zip_dispatch(info: ApkMemberInfo<'_>) -> Result>> { - assert_eq!(info.member_path, Path::new("libtest-so.so")); - - let test_so = Path::new(&env!("CARGO_MANIFEST_DIR")) - .join("data") - .join(info.member_path); - - let resolver = ElfResolver::open(test_so)?; - Ok(Some(Box::new(resolver))) - } - - fn zip_no_dispatch(info: ApkMemberInfo<'_>) -> Result>> { - assert_eq!(info.member_path, Path::new("libtest-so.so")); - Ok(None) - } - - fn test(dispatcher: impl ApkDispatch + 'static) { - let test_zip = Path::new(&env!("CARGO_MANIFEST_DIR")) - .join("data") - .join("test.zip"); - - let mmap = Mmap::builder().exec().open(test_zip).unwrap(); - let (sym, the_answer_addr) = find_the_answer_fn_in_zip(&mmap); - - let src = symbolize::Source::Process(symbolize::Process::new(Pid::Slf)); - let symbolizer = Symbolizer::builder().set_apk_dispatcher(dispatcher).build(); - let result = symbolizer - .symbolize_single(&src, Input::AbsAddr(the_answer_addr as Addr)) - .unwrap() - .into_sym() - .unwrap(); - - assert_eq!(result.name, "the_answer"); - assert_eq!(result.addr, sym.addr); - } - - let () = test(zip_dispatch); - let () = test(zip_no_dispatch); - } - - /// Check that we correctly propagate errors induced by a custom APK - /// dispatcher. - #[test] - fn symbolize_zip_with_custom_dispatch_errors() { - fn zip_error_dispatch(_info: ApkMemberInfo<'_>) -> Result>> { - Err(Error::with_unsupported("induced error")) - } - - fn zip_delayed_error_dispatch( - _info: ApkMemberInfo<'_>, - ) -> Result>> { - #[derive(Debug)] - struct Resolver; - - impl Symbolize for Resolver { - fn find_sym( - &self, - _addr: Addr, - _opts: &FindSymOpts, - ) -> Result, Reason>> { - unimplemented!() - } - } - - impl TranslateFileOffset for Resolver { - fn file_offset_to_virt_offset(&self, _file_offset: u64) -> Result> { - Err(Error::with_unsupported("induced error")) - } - } - - Ok(Some(Box::new(Resolver))) - } - - fn test(dispatcher: impl ApkDispatch + 'static) { - let test_zip = Path::new(&env!("CARGO_MANIFEST_DIR")) - .join("data") - .join("test.zip"); - - let mmap = Mmap::builder().exec().open(test_zip).unwrap(); - let (_sym, the_answer_addr) = find_the_answer_fn_in_zip(&mmap); - - let src = symbolize::Source::Process(symbolize::Process::new(Pid::Slf)); - let symbolizer = Symbolizer::builder().set_apk_dispatcher(dispatcher).build(); - let err = symbolizer - .symbolize_single(&src, Input::AbsAddr(the_answer_addr as Addr)) - .unwrap_err(); - - assert_eq!(err.to_string(), "induced error"); - } - - let () = test(zip_error_dispatch); - let () = test(zip_delayed_error_dispatch); - } } diff --git a/tests/blazesym.rs b/tests/blazesym.rs index 6ae1f16a..ecda27c9 100644 --- a/tests/blazesym.rs +++ b/tests/blazesym.rs @@ -45,6 +45,7 @@ use blazesym::Pid; use blazesym::Result; use blazesym::SymType; use blazesym::__private::find_the_answer_fn; +use blazesym::__private::find_the_answer_fn_in_zip; use blazesym::__private::zip; #[cfg(linux)] @@ -764,6 +765,30 @@ fn symbolize_process_in_mount_namespace() { let _status = child.wait().unwrap(); } +/// Check that we can symbolize an address residing in a zip archive. +#[test] +fn symbolize_process_zip() { + let test_zip = Path::new(&env!("CARGO_MANIFEST_DIR")) + .join("data") + .join("test.zip"); + + let mmap = Mmap::builder().exec().open(test_zip).unwrap(); + let (sym, the_answer_addr) = find_the_answer_fn_in_zip(&mmap); + + // Symbolize the address we just looked up. It should be correctly + // mapped to the `the_answer` function within our process. + let src = symbolize::Source::Process(symbolize::Process::new(Pid::Slf)); + let symbolizer = Symbolizer::new(); + let result = symbolizer + .symbolize_single(&src, symbolize::Input::AbsAddr(the_answer_addr)) + .unwrap() + .into_sym() + .unwrap(); + + assert_eq!(result.name, "the_answer"); + assert_eq!(result.addr, sym.addr); +} + /// Test that we can use a custom dispatch function when symbolizing addresses /// in processes. #[test] @@ -812,6 +837,104 @@ fn symbolize_process_with_custom_dispatch() { test(process_no_dispatch); } +/// Check that we can symbolize an address residing in a zip archive, using +/// a custom APK dispatcher. +#[test] +fn symbolize_zip_with_custom_dispatch() { + fn zip_dispatch(info: symbolize::ApkMemberInfo<'_>) -> Result>> { + assert_eq!(info.member_path, Path::new("libtest-so.so")); + + let test_so = Path::new(&env!("CARGO_MANIFEST_DIR")) + .join("data") + .join(info.member_path); + + let resolver = ElfResolver::open(test_so)?; + Ok(Some(Box::new(resolver))) + } + + fn zip_no_dispatch(info: symbolize::ApkMemberInfo<'_>) -> Result>> { + assert_eq!(info.member_path, Path::new("libtest-so.so")); + Ok(None) + } + + fn test(dispatcher: impl ApkDispatch + 'static) { + let test_zip = Path::new(&env!("CARGO_MANIFEST_DIR")) + .join("data") + .join("test.zip"); + + let mmap = Mmap::builder().exec().open(test_zip).unwrap(); + let (sym, the_answer_addr) = find_the_answer_fn_in_zip(&mmap); + + let src = symbolize::Source::Process(symbolize::Process::new(Pid::Slf)); + let symbolizer = Symbolizer::builder().set_apk_dispatcher(dispatcher).build(); + let result = symbolizer + .symbolize_single(&src, Input::AbsAddr(the_answer_addr as Addr)) + .unwrap() + .into_sym() + .unwrap(); + + assert_eq!(result.name, "the_answer"); + assert_eq!(result.addr, sym.addr); + } + + let () = test(zip_dispatch); + let () = test(zip_no_dispatch); +} + +/// Check that we correctly propagate errors induced by a custom APK +/// dispatcher. +#[test] +fn symbolize_zip_with_custom_dispatch_errors() { + fn zip_error_dispatch(_info: symbolize::ApkMemberInfo<'_>) -> Result>> { + Err(Error::with_unsupported("induced error")) + } + + fn zip_delayed_error_dispatch( + _info: symbolize::ApkMemberInfo<'_>, + ) -> Result>> { + #[derive(Debug)] + struct Resolver; + + impl symbolize::Symbolize for Resolver { + fn find_sym( + &self, + _addr: Addr, + _opts: &FindSymOpts, + ) -> Result, Reason>> { + unimplemented!() + } + } + + impl symbolize::TranslateFileOffset for Resolver { + fn file_offset_to_virt_offset(&self, _file_offset: u64) -> Result> { + Err(Error::with_unsupported("induced error")) + } + } + + Ok(Some(Box::new(Resolver))) + } + + fn test(dispatcher: impl symbolize::ApkDispatch + 'static) { + let test_zip = Path::new(&env!("CARGO_MANIFEST_DIR")) + .join("data") + .join("test.zip"); + + let mmap = Mmap::builder().exec().open(test_zip).unwrap(); + let (_sym, the_answer_addr) = find_the_answer_fn_in_zip(&mmap); + + let src = symbolize::Source::Process(symbolize::Process::new(Pid::Slf)); + let symbolizer = Symbolizer::builder().set_apk_dispatcher(dispatcher).build(); + let err = symbolizer + .symbolize_single(&src, symbolize::Input::AbsAddr(the_answer_addr as Addr)) + .unwrap_err(); + + assert_eq!(err.to_string(), "induced error"); + } + + let () = test(zip_error_dispatch); + let () = test(zip_delayed_error_dispatch); +} + /// Test symbolization of a kernel address inside a BPF program. #[cfg(linux)] #[test]