Skip to content

Commit

Permalink
Automatically detect language, drop unnecessary comp unit attrvals
Browse files Browse the repository at this point in the history
  • Loading branch information
matux committed Apr 26, 2023
1 parent 8c8c207 commit 07b4c5e
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 92 deletions.
3 changes: 0 additions & 3 deletions atorsl/src/data/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ pub enum Error {
#[error("vmaddr: __TEXT segment not found")]
VmAddrTextSegmentNotFound,

#[error("Compilation unit for address has no name: {0}")]
CompUnitNameMissing(Addr),

#[error("Compilation unit for address has no path: {0}")]
CompUnitDirMissing(Addr),

Expand Down
65 changes: 32 additions & 33 deletions atorsl/src/demangler.rs
Original file line number Diff line number Diff line change
@@ -1,69 +1,68 @@
use crate::IsOkAnd;
use gimli::DwLang;
use msvc_demangler::DemangleFlags;
use std::convert::identity;
use swift::Scope;

pub fn language_of(s: &str) -> DwLang {
pub enum Lang {
C,
Cpp,
ObjC,
ObjCpp,
Rust,
Swift,
}

pub fn language_of(s: &str) -> Option<Lang> {
if (s.starts_with("-[") || s.starts_with("+[")) && s.ends_with(']') {
gimli::DW_LANG_ObjC
Some(Lang::ObjC)
} else if s.starts_with("_Z")
|| s.starts_with("__Z")
|| s.starts_with("___Z")
|| s.starts_with("____Z")
|| s.starts_with('?')
|| s.starts_with("@?")
{
gimli::DW_LANG_C_plus_plus
Some(Lang::Cpp)
} else if s.starts_with("_R") {
gimli::DW_LANG_Rust
Some(Lang::Rust)
} else if swift::is_mangled(s).is_ok_and(identity) {
gimli::DW_LANG_Swift
Some(Lang::Swift)
} else {
DwLang(0)
None
}
}

pub fn demangle(sym: &str, lang: Option<DwLang>) -> String {
match lang.unwrap_or_else(|| language_of(sym)) {
gimli::DW_LANG_C
| gimli::DW_LANG_C89
| gimli::DW_LANG_C99
| gimli::DW_LANG_C11
| gimli::DW_LANG_C17
| gimli::DW_LANG_C_plus_plus
| gimli::DW_LANG_C_plus_plus_03
| gimli::DW_LANG_C_plus_plus_11
| gimli::DW_LANG_C_plus_plus_14
| gimli::DW_LANG_C_plus_plus_17
| gimli::DW_LANG_C_plus_plus_20 => {
if sym.starts_with('?') || sym.starts_with("@?") {
msvc_demangler::demangle(sym, msvc_demangler::DemangleFlags::llvm()).ok()
pub fn demangle(symbol: &str) -> String {
match language_of(symbol) {
Some(Lang::C | Lang::Cpp) => {
if symbol.starts_with('?') || symbol.starts_with("@?") {
msvc_demangler::demangle(symbol, DemangleFlags::llvm()).ok()
} else {
cpp_demangle::Symbol::new(sym)
.ok()
cpp_demangle::Symbol::new(symbol)
.map(|s| s.to_string())
.ok()
}
}

gimli::DW_LANG_ObjC | gimli::DW_LANG_ObjC_plus_plus => {
if (sym.starts_with("-[") || sym.starts_with("+[")) && sym.ends_with(']') {
Some(Lang::ObjC | Lang::ObjCpp) => {
if (symbol.starts_with("-[") || symbol.starts_with("+[")) && symbol.ends_with(']') {
None
} else {
cpp_demangle::Symbol::new(sym)
cpp_demangle::Symbol::new(symbol)
.ok()
.map(|s| s.to_string())
}
}

gimli::DW_LANG_Swift => swift::try_demangle(sym, Scope::Compact).ok(),
Some(Lang::Swift) => swift::try_demangle(symbol, Scope::Compact).ok(),

gimli::DW_LANG_Rust => rustc_demangle::try_demangle(sym)
.ok()
.map(|s| s.to_string()),
Some(Lang::Rust) => rustc_demangle::try_demangle(symbol)
.map(|s| s.to_string())
.ok(),

_ => None,
None => None,
}
.unwrap_or_else(|| sym.to_string())
.unwrap_or_else(|| symbol.to_string())
}

pub mod swift {
Expand Down
78 changes: 22 additions & 56 deletions atorsl/src/symbolicator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,32 +16,12 @@ pub fn atos_dwarf(dwarf: &Dwarf, addr: Addr, include_inlined: bool) -> Result<Ve
let unit = dwarf.unit_from_addr(&addr)?;
let mut entries = unit.entries();

let builder = &mut CompilationUnitBuilder::default();

let (_, comp_unit) = entries
.next_dfs()?
.ok_or_else(|| Error::AddrNotFound(addr))?;

let comp_unit = comp_unit
.attrs()
.fold(builder, |builder, attr| {
Ok(match attr.name() {
gimli::DW_AT_name => builder.name(
dwarf
.attr_lossy_string(&unit, attr.value())?
.into_owned(),
),
gimli::DW_AT_comp_dir => builder.dir(PathBuf::from(
&*dwarf.attr_lossy_string(&unit, attr.value())?,
)),
gimli::DW_AT_language => match attr.value() {
AttrValue::Language(dw_lang) => builder.lang(dw_lang),
_ => builder,
},
_ => builder,
})
})?
.build()?;
let comp_dir = PathBuf::from(
&*unit
.comp_dir
.ok_or(Error::CompUnitDirMissing(addr))?
.to_string_lossy(),
);

let mut debug_line_rows = unit
.line_program
Expand All @@ -67,10 +47,10 @@ pub fn atos_dwarf(dwarf: &Dwarf, addr: Addr, include_inlined: bool) -> Result<Ve
if !subprogram.has_children() {
symbols.push(Symbol {
addr,
name: demangler::demangle(&dwarf.entry_symbol(subprogram, &unit)?, comp_unit.lang),
name: demangler::demangle(&dwarf.entry_symbol(subprogram, &unit)?),
loc: Either::Left(Some(dwarf.entry_debug_line(
&addr,
&comp_unit.dir,
&comp_dir,
&mut debug_line_rows,
&unit,
)?)),
Expand All @@ -90,18 +70,16 @@ pub fn atos_dwarf(dwarf: &Dwarf, addr: Addr, include_inlined: bool) -> Result<Ve
break parent;
}

if child.tag() == gimli::DW_TAG_inlined_subroutine
&& dwarf.entry_contains(child, &addr, &unit)
{
if matches!(
child.tag(),
gimli::DW_TAG_inlined_subroutine if dwarf.entry_contains(child, &addr, &unit)
) {
symbols.insert(
0,
Symbol {
addr,
name: demangler::demangle(
&dwarf.entry_symbol(&parent, &unit)?,
comp_unit.lang,
),
loc: Either::Left(dwarf.entry_source_loc(child, &comp_unit.dir, &unit)),
name: demangler::demangle(&dwarf.entry_symbol(&parent, &unit)?),
loc: Either::Left(dwarf.entry_source_loc(child, &comp_dir, &unit)),
},
);

Expand All @@ -113,13 +91,10 @@ pub fn atos_dwarf(dwarf: &Dwarf, addr: Addr, include_inlined: bool) -> Result<Ve
0,
Symbol {
addr,
name: demangler::demangle(
&dwarf.entry_symbol(&last_child, &unit)?,
comp_unit.lang,
),
name: demangler::demangle(&dwarf.entry_symbol(&last_child, &unit)?),
loc: Either::Left(Some(dwarf.entry_debug_line(
&addr,
&comp_unit.dir,
&comp_dir,
&mut debug_line_rows,
&unit,
)?)),
Expand All @@ -138,7 +113,7 @@ pub fn atos_obj(obj: &object::File, addr: Addr) -> Result<Vec<Symbol>, Error> {

Ok(vec![Symbol {
addr: Addr::from(symbol.address()),
name: demangler::demangle(symbol.name(), None),
name: demangler::demangle(symbol.name()),
loc: Either::Right(addr - symbol.address()),
}])
}
Expand Down Expand Up @@ -210,23 +185,14 @@ impl DwarfExt for Dwarf<'_> {
if row.address() == addr {
let path = row
.file(header)
.ok_or_else(|| Error::AddrFileInfoMissing(*addr))
.and_then(|file| {
let mut path = match file.directory(header) {
Some(dir) if file.directory_index() != 0 => {
PathBuf::from(&*self.attr_lossy_string(unit, dir)?)
}
_ => comp_dir.to_path_buf(),
};

path.push(&*self.attr_lossy_string(unit, file.path_name())?);

Ok(path)
})?;
.ok_or_else(|| Error::AddrFileInfoMissing(*addr))?
.path_name();

break SourceLoc {
file: path,
file: comp_dir.join(&*self.attr_lossy_string(unit, path)?),

line: row.line().map(|l| l.get()).unwrap_or_default() as u16,

col: match row.column() {
ColumnType::LeftEdge => Some(0),
ColumnType::Column(c) => Some(c.get() as u16),
Expand Down

0 comments on commit 07b4c5e

Please sign in to comment.