Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
- `Unreal4ContextRuntimeProperties::misc_primary_cpu_brand` is has been removed.
- Deprecated Python APIs have been removed:
- `CodeModule.id` and `CodeModule.name` Use `debug_id` and `code_file`, respectively.
- `DemangleFormat` and public fields of `DemangleOptions` have been removed in favor of builder methods on `DemangleOptions`.
- `Name::new` now takes both the `NameMangling` state, and the `Language` explicitly.

## 7.5.0

Expand Down
14 changes: 10 additions & 4 deletions examples/addr2line/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ use std::borrow::Borrow;
use anyhow::{Context, Result};
use clap::{clap_app, ArgMatches};

use symbolic::common::{ByteView, Name};
use symbolic::common::{ByteView, Language, Name, NameMangling};
use symbolic::debuginfo::{Function, Object};
use symbolic::demangle::Demangle;
use symbolic::demangle::{Demangle, DemangleOptions};

fn print_name<'a, N: Borrow<Name<'a>>>(name: Option<N>, matches: &ArgMatches<'_>) {
match name.as_ref().map(Borrow::borrow) {
None => print!("??"),
Some(name) if name.as_str().is_empty() => print!("??"),
Some(name) if matches.is_present("demangle") => {
print!("{}", name.try_demangle(Default::default()));
print!("{}", name.try_demangle(DemangleOptions::name_only()));
}
Some(name) => print!("{}", name),
}
Expand Down Expand Up @@ -92,7 +92,13 @@ fn execute(matches: &ArgMatches<'_>) -> Result<()> {

if matches.is_present("functions") {
if let Some(symbol) = symbol_map.lookup(addr) {
print_name(symbol.name.as_ref().map(|n| Name::new(n.as_ref())), matches);
print_name(
symbol
.name
.as_ref()
.map(|n| Name::new(n.as_ref(), NameMangling::Mangled, Language::Unknown)),
matches,
);
print_range(symbol.address, Some(symbol.size), matches);
print!("\n at ");
}
Expand Down
5 changes: 3 additions & 2 deletions examples/minidump_stackwalk/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use walkdir::WalkDir;

use symbolic::common::{Arch, ByteView, InstructionInfo, SelfCell};
use symbolic::debuginfo::{Archive, FileFormat, Object};
use symbolic::demangle::Demangle;
use symbolic::demangle::{Demangle, DemangleOptions};
use symbolic::minidump::cfi::CfiCache;
use symbolic::minidump::processor::{CodeModuleId, FrameInfoMap, ProcessState, StackFrame};
use symbolic::symcache::{LineInfo, SymCache, SymCacheError, SymCacheWriter};
Expand Down Expand Up @@ -204,7 +204,8 @@ fn print_state(
"{:>3} {}!{} [{} : {} + 0x{:x}]",
index,
module.debug_file(),
info.function_name().try_demangle(Default::default()),
info.function_name()
.try_demangle(DemangleOptions::name_only()),
info.filename(),
info.line(),
info.instruction_address() - info.line_address(),
Expand Down
8 changes: 6 additions & 2 deletions examples/symcache_debug/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ use anyhow::{anyhow, Result};
use clap::{App, Arg, ArgMatches};

use symbolic::common::{Arch, ByteView, DSymPathExt, Language};
use symbolic::debuginfo::Archive;
use symbolic::demangle::Demangle;
use symbolic::symcache::{SymCache, SymCacheWriter};
use symbolic::{debuginfo::Archive, demangle::DemangleOptions};

fn execute(matches: &ArgMatches) -> Result<()> {
let buffer;
Expand Down Expand Up @@ -95,7 +95,11 @@ fn execute(matches: &ArgMatches) -> Result<()> {
println!("No match :(");
} else {
for sym in m {
print!("{}", sym.function_name().try_demangle(Default::default()));
print!(
"{}",
sym.function_name()
.try_demangle(DemangleOptions::name_only())
);

let path = sym.path();
let line = sym.line();
Expand Down
6 changes: 3 additions & 3 deletions py/tests/test_demangle.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@

def test_swift_demangle():
mangled = "_TFC12Swift_Tester14ViewController11doSomethingfS0_FT_T_"
expected = "ViewController.doSomething(_:)"
expected = "ViewController.doSomething(ViewController)"
assert demangle_name(mangled, lang="Swift") == expected


def test_swift_demangle_implicit():
mangled = "_TFC12Swift_Tester14ViewController11doSomethingfS0_FT_T_"
expected = "ViewController.doSomething(_:)"
expected = "ViewController.doSomething(ViewController)"
assert demangle_name(mangled) == expected


Expand All @@ -21,7 +21,7 @@ def test_swift_demangle_options():
)
simplified_expected = (
u"protocol witness for static _ObjectiveCBridgeable._"
u"unconditionallyBridgeFromObjectiveC(_:) "
u"unconditionallyBridgeFromObjectiveC(A._ObjectiveCType?) "
u"in conformance UIApplicationLaunchOptionsKey"
)
assert demangle_name(mangled) == simplified_expected
Expand Down
18 changes: 6 additions & 12 deletions symbolic-cabi/src/demangle.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
use symbolic::common::Name;
use symbolic::demangle::{Demangle, DemangleFormat, DemangleOptions};
use symbolic::common::{Name, NameMangling};
use symbolic::demangle::{Demangle, DemangleOptions};

use crate::core::SymbolicStr;

/// Creates a name from a string passed via FFI.
unsafe fn get_name(ident: *const SymbolicStr, lang: *const SymbolicStr) -> Name<'static> {
if lang.is_null() {
Name::new((*ident).as_str())
Name::from((*ident).as_str())
} else {
let lang = (*lang).as_str().parse().unwrap_or_default();
Name::with_language((*ident).as_str(), lang)
Name::new((*ident).as_str(), NameMangling::Unknown, lang)
}
}

Expand All @@ -23,10 +23,7 @@ ffi_fn! {
lang: *const SymbolicStr,
) -> Result<SymbolicStr> {
let name = get_name(ident, lang);
let demangled = name.try_demangle(DemangleOptions {
with_arguments: true,
format: DemangleFormat::Short,
});
let demangled = name.try_demangle(DemangleOptions::name_only().argument_types(true));

Ok(demangled.into_owned().into())
}
Expand All @@ -43,10 +40,7 @@ ffi_fn! {
lang: *const SymbolicStr,
) -> Result<SymbolicStr> {
let name = get_name(ident, lang);
let demangled = name.try_demangle(DemangleOptions {
with_arguments: false,
format: DemangleFormat::Short,
});
let demangled = name.try_demangle(DemangleOptions::name_only());

Ok(demangled.into_owned().into())
}
Expand Down
120 changes: 77 additions & 43 deletions symbolic-common/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,31 @@ impl str::FromStr for Language {
}
}

/// A [`Name`]s mangling state.
///
/// By default, the mangling of a [`Name`] is not known, but an explicit mangling state can be set
/// for Names that are guaranteed to be unmangled.
#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
serde(crate = "serde_")
)]
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum NameMangling {
/// The [`Name`] is definitely mangled.
Mangled,
/// The [`Name`] is not mangled.
Unmangled,
/// The mangling of the [`Name`] is not known.
Unknown,
}

impl Default for NameMangling {
fn default() -> Self {
NameMangling::Unknown
}
}

/// The name of a potentially mangled symbol.
///
/// Debugging information often only contains mangled names in their symbol and debug information
Expand All @@ -656,16 +681,17 @@ impl str::FromStr for Language {
/// ```
/// use symbolic_common::Name;
///
/// let name = Name::new("_ZN3foo3barEv");
/// let name = Name::from("_ZN3foo3barEv");
/// assert_eq!(name.to_string(), "_ZN3foo3barEv");
/// ```
///
/// Create a name with a language. Alternate formatting prints the language:
/// Create a name with a language and explicit mangling state.
/// Alternate formatting prints the language:
///
/// ```
/// use symbolic_common::{Language, Name};
/// use symbolic_common::{Language, Name, NameMangling};
///
/// let name = Name::with_language("_ZN3foo3barEv", Language::Cpp);
/// let name = Name::new("_ZN3foo3barEv", NameMangling::Mangled, Language::Cpp);
/// assert_eq!(format!("{:#}", name), "_ZN3foo3barEv [C++]");
/// ```
///
Expand All @@ -679,52 +705,34 @@ impl str::FromStr for Language {
pub struct Name<'a> {
string: Cow<'a, str>,
lang: Language,
#[cfg_attr(feature = "serde", serde(default))]
mangling: NameMangling,
}

impl<'a> Name<'a> {
/// Constructs a new mangled name.
///
/// The language of this name is `Language::Unknown`.
/// Constructs a new Name with given mangling and language.
///
/// # Example
/// In case both the mangling state and the language are unknown, a simpler alternative to use
/// is [`Name::from`].
///
/// ```
/// use symbolic_common::Name;
///
/// let name = Name::new("_ZN3foo3barEv");
/// assert_eq!(name.to_string(), "_ZN3foo3barEv");
/// ```
#[inline]
pub fn new<S>(string: S) -> Self
where
S: Into<Cow<'a, str>>,
{
Name {
string: string.into(),
lang: Language::Unknown,
}
}

/// Constructs a new mangled name with a known [`Language`].
///
/// # Example
///
/// ```
/// use symbolic_common::{Language, Name};
/// use symbolic_common::{Language, Name, NameMangling};
///
/// let name = Name::with_language("_ZN3foo3barEv", Language::Cpp);
/// let name = Name::new("_ZN3foo3barEv", NameMangling::Mangled, Language::Cpp);
/// assert_eq!(format!("{:#}", name), "_ZN3foo3barEv [C++]");
/// ```
///
/// [`Language`]: enum.Language.html
#[inline]
pub fn with_language<S>(string: S, lang: Language) -> Self
pub fn new<S>(string: S, mangling: NameMangling, lang: Language) -> Self
where
S: Into<Cow<'a, str>>,
{
Name {
string: string.into(),
lang,
mangling,
}
}

Expand All @@ -733,24 +741,30 @@ impl<'a> Name<'a> {
/// # Example
///
/// ```
/// use symbolic_common::Name;
/// use symbolic_common::{Language, Name, NameMangling};
///
/// let name = Name::new("_ZN3foo3barEv");
/// let name = Name::new("_ZN3foo3barEv", NameMangling::Mangled, Language::Cpp);
/// assert_eq!(name.as_str(), "_ZN3foo3barEv");
/// ```
///
/// This is also available as an `AsRef<str>` implementation:
///
/// ```
/// use symbolic_common::Name;
/// use symbolic_common::{Language, Name, NameMangling};
///
/// let name = Name::new("_ZN3foo3barEv");
/// let name = Name::new("_ZN3foo3barEv", NameMangling::Mangled, Language::Cpp);
/// assert_eq!(name.as_ref(), "_ZN3foo3barEv");
/// ```
pub fn as_str(&self) -> &str {
&self.string
}

/// Set the `Name`'s language.
pub fn set_language(&mut self, language: Language) -> &mut Self {
self.lang = language;
self
}

/// The language of the mangled symbol.
///
/// If the language is not declared in the source, this returns `Language::Unknown`. The
Expand All @@ -760,37 +774,57 @@ impl<'a> Name<'a> {
/// # Example
///
/// ```
/// use symbolic_common::{Language, Name};
/// use symbolic_common::{Language, Name, NameMangling};
///
/// let name = Name::new("_ZN3foo3barEv");
/// assert_eq!(name.language(), Language::Unknown);
/// let name = Name::new("_ZN3foo3barEv", NameMangling::Mangled, Language::Cpp);
/// assert_eq!(name.language(), Language::Cpp);
/// ```
pub fn language(&self) -> Language {
self.lang
}

/// Converts this name into a `Cow`, dropping the language.
/// Set the `Name`'s mangling state.
pub fn set_mangling(&mut self, mangling: NameMangling) -> &mut Self {
self.mangling = mangling;
self
}

/// Returns the `Name`'s mangling state.
///
/// # Example
///
/// ```
/// use symbolic_common::{Language, Name, NameMangling};
///
/// let unmangled = Name::new("foo::bar", NameMangling::Unmangled, Language::Unknown);
/// assert_eq!(unmangled.mangling(), NameMangling::Unmangled);
/// ```
pub fn mangling(&self) -> NameMangling {
self.mangling
}

/// Converts this name into a [`Cow`].
///
/// # Example
///
/// ```
/// use symbolic_common::Name;
///
/// let name = Name::new("_ZN3foo3barEv");
/// let name = Name::from("_ZN3foo3barEv");
/// assert_eq!(name.into_cow(), "_ZN3foo3barEv");
/// ```
pub fn into_cow(self) -> Cow<'a, str> {
self.string
}

/// Converts this name into a `String`, dropping the language.
/// Converts this name into a [`String`].
///
/// # Example
///
/// ```
/// use symbolic_common::Name;
///
/// let name = Name::new("_ZN3foo3barEv");
/// let name = Name::from("_ZN3foo3barEv");
/// assert_eq!(name.into_string(), "_ZN3foo3barEv");
/// ```
pub fn into_string(self) -> String {
Expand All @@ -815,7 +849,7 @@ where
S: Into<Cow<'a, str>>,
{
fn from(string: S) -> Self {
Self::new(string)
Self::new(string, NameMangling::Unknown, Language::Unknown)
}
}

Expand Down
4 changes: 2 additions & 2 deletions symbolic-debuginfo/src/breakpad.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::str;
use pest::Parser;
use thiserror::Error;

use symbolic_common::{Arch, AsSelf, CodeId, DebugId, Name};
use symbolic_common::{Arch, AsSelf, CodeId, DebugId, Language, Name, NameMangling};

use crate::base::*;
use crate::private::{Lines, Parse};
Expand Down Expand Up @@ -1138,7 +1138,7 @@ impl<'s> BreakpadFunctionIterator<'s> {
Ok(Function {
address: record.address,
size: record.size,
name: Name::from(record.name),
name: Name::new(record.name, NameMangling::Unmangled, Language::Unknown),
compilation_dir: &[],
lines,
inlinees: Vec::new(),
Expand Down
Loading