From 535e2219edfc816a15c0795ab7d8afa0eec578bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=BCller?= Date: Fri, 15 Sep 2023 16:06:26 -0700 Subject: [PATCH] Start with flattening --- src/c_api/symbolize.rs | 2 +- src/dwarf/resolver.rs | 6 +-- src/elf/resolver.rs | 9 ++-- src/gsym/resolver.rs | 12 ++--- src/kernel.rs | 6 +-- src/ksym.rs | 9 ++-- src/resolver.rs | 5 +- src/symbolize/symbolizer.rs | 95 +++++++++++++++++++------------------ 8 files changed, 74 insertions(+), 70 deletions(-) diff --git a/src/c_api/symbolize.rs b/src/c_api/symbolize.rs index 0f99205fe..1534292f4 100644 --- a/src/c_api/symbolize.rs +++ b/src/c_api/symbolize.rs @@ -325,7 +325,7 @@ pub unsafe extern "C" fn blaze_symbolizer_free(symbolizer: *mut blaze_symbolizer /// /// The returned pointer should be released using [`blaze_result_free`] once /// usage concluded. -fn convert_symbolizedresults_to_c(results: Vec>) -> *const blaze_result { +fn convert_symbolizedresults_to_c(results: Vec>) -> *const blaze_result { // Allocate a buffer to contain a blaze_result, all // blaze_sym, and C strings of symbol and path. let strtab_size = results.iter().flatten().fold(0, |acc, result| { diff --git a/src/dwarf/resolver.rs b/src/dwarf/resolver.rs index 68da406df..c0d4273d6 100644 --- a/src/dwarf/resolver.rs +++ b/src/dwarf/resolver.rs @@ -125,7 +125,7 @@ impl DwarfResolver { } /// Lookup the symbol(s) at an address. - pub(crate) fn find_syms(&self, addr: Addr) -> Result>, Error> { + pub(crate) fn find_sym(&self, addr: Addr) -> Result>, Error> { // TODO: This conditional logic is weird and potentially // unnecessary. Consider removing it or moving it higher // in the call chain. @@ -151,9 +151,9 @@ impl DwarfResolver { addr, lang: language.into(), }; - Ok(vec![sym]) + Ok(Some(sym)) } else { - Ok(Vec::new()) + Ok(None) } } diff --git a/src/elf/resolver.rs b/src/elf/resolver.rs index 97e566f1f..824a29186 100644 --- a/src/elf/resolver.rs +++ b/src/elf/resolver.rs @@ -56,7 +56,7 @@ impl ElfResolver { impl SymResolver for ElfResolver { #[cfg_attr(feature = "tracing", crate::log::instrument(fields(addr = format_args!("{addr:#x}"))))] - fn find_syms(&self, addr: Addr) -> Result>> { + fn find_sym(&self, addr: Addr) -> Result>> { let parser = self.get_parser(); if let Some((name, addr)) = parser.find_sym(addr, STT_FUNC)? { // ELF does not carry any source code language information. @@ -65,13 +65,14 @@ impl SymResolver for ElfResolver { // TODO: Long term we probably want a different heuristic here, as // there can be valid differences between the two formats // (e.g., DWARF could contain more symbols). - return Ok(vec![IntSym { name, addr, lang }]) + let sym = IntSym { name, addr, lang }; + return Ok(Some(sym)) } match &self.backend { #[cfg(feature = "dwarf")] - ElfBackend::Dwarf(dwarf) => dwarf.find_syms(addr), - ElfBackend::Elf(_) => Ok(Vec::new()), + ElfBackend::Dwarf(dwarf) => dwarf.find_sym(addr), + ElfBackend::Elf(_) => Ok(None), } } diff --git a/src/gsym/resolver.rs b/src/gsym/resolver.rs index b0e5cc601..163606c29 100644 --- a/src/gsym/resolver.rs +++ b/src/gsym/resolver.rs @@ -142,14 +142,14 @@ impl<'dat> GsymResolver<'dat> { } impl SymResolver for GsymResolver<'_> { - fn find_syms(&self, addr: Addr) -> Result>> { + fn find_sym(&self, addr: Addr) -> Result>> { if let Some(idx) = self.ctx.find_addr(addr) { let found = self .ctx .addr_at(idx) .ok_or_invalid_data(|| format!("failed to read address table entry {idx}"))?; if addr < found { - return Ok(Vec::new()) + return Ok(None) } let info = self @@ -171,9 +171,9 @@ impl SymResolver for GsymResolver<'_> { lang, }; - Ok(vec![sym]) + Ok(Some(sym)) } else { - Ok(Vec::new()) + Ok(None) } } @@ -353,9 +353,7 @@ mod tests { // always fall into the inlined region, no matter toolchain. If not, add // padding bytes/dummy instructions and adjust some more. let addr = 0x200020a; - let syms = resolver.find_syms(addr).unwrap(); - assert_eq!(syms.len(), 1); - let sym = &syms[0]; + let sym = resolver.find_sym(addr).unwrap(); assert_eq!(sym.name, "factorial_inline_test"); let info = resolver.find_line_info(addr).unwrap().unwrap(); diff --git a/src/kernel.rs b/src/kernel.rs index 1d912f603..5f6e1d661 100644 --- a/src/kernel.rs +++ b/src/kernel.rs @@ -40,11 +40,11 @@ impl KernelResolver { } impl SymResolver for KernelResolver { - fn find_syms(&self, addr: Addr) -> Result>> { + fn find_sym(&self, addr: Addr) -> Result>> { if let Some(ksym_resolver) = self.ksym_resolver.as_ref() { - ksym_resolver.find_syms(addr) + ksym_resolver.find_sym(addr) } else { - self.elf_resolver.as_ref().unwrap().find_syms(addr) + self.elf_resolver.as_ref().unwrap().find_sym(addr) } } diff --git a/src/ksym.rs b/src/ksym.rs index 38172fbdd..a85efc9a9 100644 --- a/src/ksym.rs +++ b/src/ksym.rs @@ -103,7 +103,7 @@ impl KSymResolver { } } - pub fn find_addresses_ksym(&self, addr: Addr) -> impl Iterator { + pub fn find_ksym(&self, addr: Addr) -> Option<&Ksym> { let mut l = 0; let mut r = self.syms.len(); @@ -125,6 +125,7 @@ impl KSymResolver { .iter() .rev() .take_while(move |sym| sym.addr == self.syms[l - 1].addr) + .next() } #[cfg(test)] @@ -146,9 +147,9 @@ impl KSymResolver { } impl SymResolver for KSymResolver { - fn find_syms(&self, addr: Addr) -> Result>> { - let syms = self.find_addresses_ksym(addr).map(IntSym::from).collect(); - Ok(syms) + fn find_sym(&self, addr: Addr) -> Result>> { + let sym = self.find_ksym(addr).map(IntSym::from); + Ok(sym) } fn find_addr(&self, name: &str, opts: &FindAddrOpts) -> Result> { diff --git a/src/resolver.rs b/src/resolver.rs index 941388849..f797c0bfa 100644 --- a/src/resolver.rs +++ b/src/resolver.rs @@ -39,9 +39,8 @@ pub(crate) trait SymResolver where Self: Debug, { - /// Find the names and the start addresses of a symbol found for - /// the given address. - fn find_syms(&self, addr: Addr) -> Result>>; + /// Find the symbol corresponding to the given address. + fn find_sym(&self, addr: Addr) -> Result>>; /// Find the address and size of a symbol name. fn find_addr(&self, name: &str, opts: &FindAddrOpts) -> Result>; /// Find the file name and the line number of an address. diff --git a/src/symbolize/symbolizer.rs b/src/symbolize/symbolizer.rs index 8edbd4f79..ba19bf2e9 100644 --- a/src/symbolize/symbolizer.rs +++ b/src/symbolize/symbolizer.rs @@ -249,11 +249,16 @@ impl Symbolizer { /// Symbolize an address using the provided [`SymResolver`]. #[cfg_attr(feature = "tracing", crate::log::instrument(skip_all, fields(addr = format_args!("{addr:#x}"), resolver = ?resolver)))] - fn symbolize_with_resolver(&self, addr: Addr, resolver: &dyn SymResolver) -> Result> { - let syms = resolver.find_syms(addr)?; - if syms.is_empty() { - return Ok(Vec::new()) - } + fn symbolize_with_resolver( + &self, + addr: Addr, + resolver: &dyn SymResolver, + ) -> Result> { + let sym = if let Some(sym) = resolver.find_sym(addr)? { + sym + } else { + return Ok(None) + }; let src_loc = if self.src_location { resolver.find_line_info(addr)? @@ -261,58 +266,58 @@ impl Symbolizer { None }; - let mut results = Vec::with_capacity(syms.len()); - for sym in syms { - let code_info = src_loc.as_ref().map(|src_loc| CodeInfo { - dir: Some(src_loc.direct.dir.to_path_buf()), - file: src_loc.direct.file.to_os_string(), - line: src_loc.direct.line, - column: src_loc.direct.column, - _non_exhaustive: (), - }); - - let IntSym { - name, - addr: sym_addr, - lang, - } = sym; - - let sym = Sym { - name: self.maybe_demangle(name, lang), - addr: sym_addr, - offset: addr - sym_addr, - code_info, - inlined: Vec::new(), - _non_exhaustive: (), - }; - let () = results.push(sym); - } - Ok(results) + let code_info = src_loc.as_ref().map(|src_loc| CodeInfo { + dir: Some(src_loc.direct.dir.to_path_buf()), + file: src_loc.direct.file.to_os_string(), + line: src_loc.direct.line, + column: src_loc.direct.column, + _non_exhaustive: (), + }); + + let IntSym { + name, + addr: sym_addr, + lang, + } = sym; + + let sym = Sym { + name: self.maybe_demangle(name, lang), + addr: sym_addr, + offset: addr - sym_addr, + code_info, + inlined: Vec::new(), + _non_exhaustive: (), + }; + Ok(Some(sym)) } /// Symbolize a list of addresses using the provided [`SymResolver`]. - fn symbolize_addrs(&self, addrs: &[Addr], resolver: &dyn SymResolver) -> Result>> { + fn symbolize_addrs( + &self, + addrs: &[Addr], + resolver: &dyn SymResolver, + ) -> Result>> { addrs .iter() .map(|addr| self.symbolize_with_resolver(*addr, resolver)) .collect() } - fn resolve_addr_in_elf(&self, addr: Addr, path: &Path) -> Result> { + fn resolve_addr_in_elf(&self, addr: Addr, path: &Path) -> Result> { let backend = self.elf_cache.find(path)?; let resolver = ElfResolver::with_backend(path, backend)?; - let symbols = self.symbolize_with_resolver(addr, &resolver)?; - Ok(symbols) + let symbol = self.symbolize_with_resolver(addr, &resolver)?; + Ok(symbol) } /// Symbolize the given list of user space addresses in the provided /// process. - fn symbolize_user_addrs(&self, addrs: &[Addr], pid: Pid) -> Result>> { + fn symbolize_user_addrs(&self, addrs: &[Addr], pid: Pid) -> Result>> { struct SymbolizeHandler<'sym> { /// The "outer" `Symbolizer` instance. symbolizer: &'sym Symbolizer, /// Symbols representing the symbolized addresses. - all_symbols: Vec>, + all_symbols: Vec>, } impl SymbolizeHandler<'_> { @@ -325,17 +330,17 @@ impl Symbolizer { let backend = ElfBackend::Elf(Rc::new(elf_parser)); let resolver = ElfResolver::with_backend(&apk_elf_path, backend)?; - let symbols = self + let symbol = self .symbolizer .symbolize_with_resolver(norm_addr, &resolver)?; - let () = self.all_symbols.push(symbols); + let () = self.all_symbols.push(symbol); Ok(()) } fn handle_elf_addr(&mut self, addr: Addr, entry: &PathMapsEntry) -> Result<()> { let path = &entry.path.maps_file; let norm_addr = normalize_elf_addr(addr, entry)?; - let symbols = self + let symbol = self .symbolizer .resolve_addr_in_elf(norm_addr, path) .with_context(|| { @@ -344,7 +349,7 @@ impl Symbolizer { path.display() ) })?; - let () = self.all_symbols.push(symbols); + let () = self.all_symbols.push(symbol); Ok(()) } } @@ -352,7 +357,7 @@ impl Symbolizer { impl normalize::Handler for SymbolizeHandler<'_> { #[cfg_attr(feature = "tracing", crate::log::instrument(skip_all, fields(addr = format_args!("{_addr:#x}"))))] fn handle_unknown_addr(&mut self, _addr: Addr) -> Result<()> { - let () = self.all_symbols.push(Vec::new()); + let () = self.all_symbols.push(None); Ok(()) } @@ -383,7 +388,7 @@ impl Symbolizer { Ok(handler.all_symbols) } - fn symbolize_kernel_addrs(&self, addrs: &[Addr], src: &Kernel) -> Result>> { + fn symbolize_kernel_addrs(&self, addrs: &[Addr], src: &Kernel) -> Result>> { let Kernel { kallsyms, kernel_image, @@ -460,7 +465,7 @@ impl Symbolizer { /// Symbolize a list of addresses according to the configuration /// provided via `src`. #[cfg_attr(feature = "tracing", crate::log::instrument(skip_all, fields(src = ?src, addrs = format_args!("{addrs:#x?}"))))] - pub fn symbolize(&self, src: &Source, addrs: &[Addr]) -> Result>> { + pub fn symbolize(&self, src: &Source, addrs: &[Addr]) -> Result>> { match src { Source::Elf(Elf { path,