From d747ba311ca413cf3d085868db9132490ee7cc8c Mon Sep 17 00:00:00 2001 From: sudoBash418 Date: Sun, 8 Sep 2024 01:20:36 -0600 Subject: [PATCH] Extract ZIP-embedded path splitting into a function --- src/symbolize/gimli.rs | 17 ++++++++++++++++- src/symbolize/gimli/elf.rs | 7 +------ src/symbolize/gimli/libs_dl_iterate_phdr.rs | 15 ++++++--------- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/symbolize/gimli.rs b/src/symbolize/gimli.rs index 7710b760..9a82179d 100644 --- a/src/symbolize/gimli.rs +++ b/src/symbolize/gimli.rs @@ -14,7 +14,7 @@ use core::convert::TryInto; use core::mem; use core::u32; use libc::c_void; -use mystd::ffi::OsString; +use mystd::ffi::{OsStr, OsString}; use mystd::fs::File; use mystd::path::Path; use mystd::prelude::v1::*; @@ -322,6 +322,21 @@ fn create_mapping(lib: &Library) -> Option { } } +/// Try to extract the archive path from an "embedded" library path +/// (e.g. `/path/to/my.apk` from `/path/to/my.apk!/mylib.so`). +/// +/// Returns `None` if the path does not contain a `!/` separator. +#[cfg(target_os = "android")] +fn extract_zip_path_android(path: &OsStr) -> Option<&OsStr> { + use mystd::os::unix::ffi::OsStrExt; + + path.as_bytes() + .windows(2) + .enumerate() + .find(|(_, chunk)| chunk == b"!/") + .map(|(index, _)| OsStr::from_bytes(path.as_bytes().split_at(index).0)) +} + // unsafe because this is required to be externally synchronized pub unsafe fn clear_symbol_cache() { Cache::with_global(|cache| cache.mappings.clear()); diff --git a/src/symbolize/gimli/elf.rs b/src/symbolize/gimli/elf.rs index a23501df..48c7c953 100644 --- a/src/symbolize/gimli/elf.rs +++ b/src/symbolize/gimli/elf.rs @@ -59,12 +59,7 @@ impl Mapping { pub fn new_android(path: &Path, zip_offset: Option) -> Option { fn map_embedded_library(path: &Path, zip_offset: u64) -> Option { // get path of ZIP archive (delimited by `!/`) - let raw_path = path.as_os_str().as_bytes(); - let zip_path = raw_path - .windows(2) - .enumerate() - .find(|(_, chunk)| chunk == b"!/") - .map(|(index, _)| Path::new(OsStr::from_bytes(raw_path.split_at(index).0)))?; + let zip_path = Path::new(super::extract_zip_path_android(path.as_os_str())?); let file = fs::File::open(zip_path).ok()?; let len = file.metadata().ok()?.len(); diff --git a/src/symbolize/gimli/libs_dl_iterate_phdr.rs b/src/symbolize/gimli/libs_dl_iterate_phdr.rs index ebae78a5..0edb9c7c 100644 --- a/src/symbolize/gimli/libs_dl_iterate_phdr.rs +++ b/src/symbolize/gimli/libs_dl_iterate_phdr.rs @@ -89,15 +89,12 @@ unsafe extern "C" fn callback( // only check for ZIP-embedded file if we have data from /proc/self/maps maps.as_ref().and_then(|maps| { // check if file is embedded within a ZIP archive by searching for `!/` - name.as_bytes() - .windows(2) - .find(|&chunk| chunk == b"!/") - .and_then(|_| { - // find MapsEntry matching library's base address - maps.iter() - .find(|m| m.ip_matches(dlpi_addr as usize)) - .and_then(|m| Some(m.offset())) - }) + super::extract_zip_path_android(&name).and_then(|_| { + // find MapsEntry matching library's base address and get its file offset + maps.iter() + .find(|m| m.ip_matches(dlpi_addr as usize)) + .map(|m| m.offset()) + }) }) }; let headers = if dlpi_phdr.is_null() || dlpi_phnum == 0 {