Skip to content

Commit 6d6d890

Browse files
committed
feat: Parameterize symbol demangling on command line. (#226)
* feat: Parameterize symbol demangling on command line. This commit adds two new switched (--keep-mangled and --demangle) where --demangle is specified by default. keep-mangled can be useful when one wants to do the demangling themselves with a different library than rustc_demangle (e.g. to analyze symbol names with ast-demangle).
1 parent 7471015 commit 6d6d890

File tree

8 files changed

+78
-23
lines changed

8 files changed

+78
-23
lines changed

.github/workflows/check-and-lint.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,15 @@ jobs:
4343
- name: Native version of cargo-show-asm (Intel ASM) + atom
4444
run: cargo run -- --manifest-path sample/Cargo.toml --target-cpu atom --intel sample::main --rust
4545

46+
- name: Native version of cargo-show-asm with symbol mangling (Intel ASM)
47+
run: cargo run -- --manifest-path sample/Cargo.toml --intel sample::main --rust --keep-mangled
48+
4649
- name: Native version of cargo-show-asm (LLVM)
4750
run: cargo run -- --manifest-path sample/Cargo.toml --llvm sample::main
4851

52+
- name: Native version of cargo-show-asm with symbol mangling (LLVM)
53+
run: cargo run -- --manifest-path sample/Cargo.toml --llvm --keep-mangled sample::main
54+
4955
- name: Native version of cargo-show-asm (LLVM Input)
5056
run: cargo run -- --manifest-path sample/Cargo.toml --llvm-input sample::main
5157

@@ -102,9 +108,15 @@ jobs:
102108
- name: Native version of cargo-show-asm (Intel ASM) + atom
103109
run: cargo run -- --manifest-path sample/Cargo.toml --target-cpu atom --intel sample::main --rust
104110

111+
- name: Native version of cargo-show-asm with symbol mangling (Intel ASM)
112+
run: cargo run -- --manifest-path sample/Cargo.toml --intel sample::main --rust --keep-mangled
113+
105114
- name: Native version of cargo-show-asm (LLVM)
106115
run: cargo run -- --manifest-path sample/Cargo.toml --llvm sample::main
107116

117+
- name: Native version of cargo-show-asm with symbol mangling (LLVM)
118+
run: cargo run -- --manifest-path sample/Cargo.toml --llvm --keep-mangled sample::main
119+
108120
- name: Native version of cargo-show-asm (LLVM Input)
109121
run: cargo run -- --manifest-path sample/Cargo.toml --llvm-input sample::main
110122

@@ -158,9 +170,15 @@ jobs:
158170
- name: Native version of cargo-show-asm (Intel ASM) + atom
159171
run: cargo run -- --manifest-path sample/Cargo.toml --target-cpu atom --intel sample::main --rust
160172

173+
- name: Native version of cargo-show-asm with symbol mangling (Intel ASM)
174+
run: cargo run -- --manifest-path sample/Cargo.toml --intel sample::main --rust --keep-mangled
175+
161176
- name: Native version of cargo-show-asm (LLVM)
162177
run: cargo run -- --manifest-path sample/Cargo.toml --llvm sample::main
163178

179+
- name: Native version of cargo-show-asm with symbol mangling (LLVM)
180+
run: cargo run -- --manifest-path sample/Cargo.toml --llvm --keep-mangled sample::main
181+
164182
- name: Native version of cargo-show-asm (LLVM Input)
165183
run: cargo run -- --manifest-path sample/Cargo.toml --llvm-input sample::main
166184

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ Show the code rustc generates for any function
115115
Disable color highlighting
116116
- **` --full-name`** —
117117
Include full demangled name instead of just prefix
118+
- **` --short-name`** —
119+
Include demangled names without hash suffix (default)
120+
- **` --keep-mangled`** —
121+
Do not demangle symbol names
118122
- **`-K`**, **`--keep-labels`** —
119123
Keep all the original labels
120124
- **`-B`**, **`--keep-blanks`** —

src/asm.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ pub fn find_items(lines: &[Statement]) -> BTreeMap<Item, Range<usize>> {
8282
let name = format!("{dem:#?}");
8383
let name_entry = names.entry(name.clone()).or_insert(0);
8484
item = Some(Item {
85+
mangled_name: label.id.to_owned(),
8586
name,
8687
hashed,
8788
index: *name_entry,
@@ -156,6 +157,7 @@ fn get_item_in_section(
156157
String::from(label.id)
157158
};
158159
return Some(Item {
160+
mangled_name: label.id.to_owned(),
159161
name: name.clone(),
160162
hashed: name,
161163
index: 0, // Written later in find_items
@@ -273,9 +275,9 @@ pub fn dump_range(
273275

274276
empty_line = false;
275277
#[allow(clippy::match_bool)]
276-
match fmt.full_name {
277-
true => safeprintln!("{line:#}"),
278-
false => safeprintln!("{line}"),
278+
match fmt.name_display {
279+
crate::opts::NameDisplay::Full => safeprintln!("{line:#}"),
280+
_ => safeprintln!("{line}"),
279281
}
280282
}
281283
}

src/lib.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
use std::{collections::BTreeMap, ops::Range};
44

5-
use opts::{Format, ToDump};
5+
use opts::{Format, NameDisplay, ToDump};
66
pub mod asm;
77
pub mod cached_lines;
88
pub mod demangle;
@@ -66,6 +66,8 @@ macro_rules! esafeprint {
6666

6767
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
6868
pub struct Item {
69+
/// mangled name
70+
pub mangled_name: String,
6971
/// demangled name
7072
pub name: String,
7173
/// demangled name with hash
@@ -76,13 +78,20 @@ pub struct Item {
7678
pub len: usize,
7779
}
7880

79-
pub fn suggest_name<'a>(search: &str, full: bool, items: impl IntoIterator<Item = &'a Item>) {
81+
pub fn suggest_name<'a>(
82+
search: &str,
83+
name_display: &NameDisplay,
84+
items: impl IntoIterator<Item = &'a Item>,
85+
) {
8086
let mut count = 0usize;
8187
let names = items.into_iter().fold(BTreeMap::new(), |mut m, item| {
8288
count += 1;
83-
m.entry(if full { &item.hashed } else { &item.name })
84-
.or_insert_with(Vec::new)
85-
.push(item.len);
89+
let entry = match name_display {
90+
NameDisplay::Full => &item.hashed,
91+
NameDisplay::Short => &item.name,
92+
NameDisplay::Mangled => &item.mangled_name,
93+
};
94+
m.entry(entry).or_insert_with(Vec::new).push(item.len);
8695
m
8796
});
8897

@@ -170,7 +179,7 @@ pub fn get_dump_range(
170179
if filtered.is_empty() {
171180
safeprintln!("Can't find any items matching {function:?}");
172181
} else {
173-
suggest_name(&function, fmt.full_name, filtered.iter().map(|x| x.0));
182+
suggest_name(&function, &fmt.name_display, filtered.iter().map(|x| x.0));
174183
}
175184
std::process::exit(1);
176185
};
@@ -180,7 +189,7 @@ pub fn get_dump_range(
180189
// Unspecified, so print suggestions and exit
181190
ToDump::Unspecified => {
182191
let items = items.into_keys().collect::<Vec<_>>();
183-
suggest_name("", fmt.full_name, &items);
192+
suggest_name("", &fmt.name_display, &items);
184193
unreachable!("suggest_name exits");
185194
}
186195
}

src/llvm.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::{
88
color,
99
demangle::{self, contents},
1010
get_dump_range,
11-
opts::{Format, ToDump},
11+
opts::{Format, NameDisplay, ToDump},
1212
safeprintln, Item,
1313
};
1414
use std::{
@@ -39,20 +39,22 @@ fn find_items(lines: &CachedLines) -> BTreeMap<Item, Range<usize>> {
3939
continue;
4040
} else if let (true, Some(name)) = (current_item.is_none(), line.strip_prefix("; ")) {
4141
current_item = Some(Item {
42+
mangled_name: name.to_owned(),
4243
name: name.to_owned(),
4344
hashed: String::new(),
4445
index: res.len(),
4546
len: ix,
4647
});
4748
} else if line.starts_with("define ") {
48-
if let (Some(cur), Some(hashed)) = (
49+
if let (Some(cur), Some((mangled_name, hashed))) = (
4950
&mut current_item,
5051
regex
5152
.captures(line)
5253
.and_then(|c| c.get(1))
5354
.map(|c| c.as_str())
54-
.and_then(demangle::demangled),
55+
.and_then(|c| Some((c.to_owned(), demangle::demangled(c)?))),
5556
) {
57+
cur.mangled_name = mangled_name;
5658
cur.hashed = format!("{hashed:?}");
5759
}
5860
} else if line == "}" {
@@ -88,7 +90,7 @@ fn dump_range(fmt: &Format, strings: &[&str]) {
8890
if line.starts_with("; ") {
8991
safeprintln!("{}", color!(line, OwoColorize::bright_black));
9092
} else {
91-
let line = demangle::contents(line, fmt.full_name);
93+
let line = demangle::contents(line, fmt.name_display == NameDisplay::Full);
9294
safeprintln!("{line}");
9395
}
9496
}
@@ -142,11 +144,11 @@ pub fn collect_or_dump(
142144
if line.starts_with("define ") {
143145
state = State::Define;
144146

145-
if let Some(hashed) = regex
147+
if let Some((mangled_name, hashed)) = regex
146148
.captures(&line)
147149
.and_then(|c| c.get(1))
148150
.map(|c| c.as_str())
149-
.and_then(demangle::demangled)
151+
.and_then(|c| Some((c.to_owned(), demangle::demangled(c)?)))
150152
{
151153
let hashed = format!("{hashed:?}");
152154
let name_entry = names.entry(name.clone()).or_insert(0);
@@ -155,6 +157,7 @@ pub fn collect_or_dump(
155157
});
156158

157159
current_item = Some(Item {
160+
mangled_name,
158161
name: name.clone(),
159162
hashed,
160163
index: *name_entry,
@@ -165,7 +168,10 @@ pub fn collect_or_dump(
165168
if seen {
166169
safeprintln!("{}", color!(name, OwoColorize::cyan));
167170
safeprintln!("{}", color!(attrs, OwoColorize::cyan));
168-
safeprintln!("{}", contents(&line, fmt.full_name));
171+
safeprintln!(
172+
"{}",
173+
contents(&line, fmt.name_display == NameDisplay::Full)
174+
);
169175
}
170176
} else {
171177
state = State::Skipping;
@@ -176,7 +182,7 @@ pub fn collect_or_dump(
176182
}
177183
State::Define => {
178184
if seen {
179-
safeprintln!("{}", contents(&line, fmt.full_name));
185+
safeprintln!("{}", contents(&line, fmt.name_display == NameDisplay::Full));
180186
}
181187
if line == "}" {
182188
if let Some(mut cur) = current_item.take() {

src/mca.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::{
66

77
use crate::{
88
demangle, esafeprintln, get_dump_range,
9-
opts::{Format, ToDump},
9+
opts::{Format, NameDisplay, ToDump},
1010
safeprintln,
1111
};
1212

@@ -87,7 +87,7 @@ pub fn dump_function(
8787

8888
for line in BufRead::lines(BufReader::new(o)) {
8989
let line = line?;
90-
let line = demangle::contents(&line, fmt.full_name);
90+
let line = demangle::contents(&line, fmt.name_display == NameDisplay::Full);
9191
safeprintln!("{line}");
9292
}
9393

src/mir.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ fn find_items(lines: &CachedLines) -> BTreeMap<Item, Range<usize>> {
3838
break;
3939
}
4040
current_item = Some(Item {
41+
mangled_name: name.to_owned(),
4142
name: name.to_owned(),
4243
hashed: name.to_owned(),
4344
index: res.len(),

src/opts.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,8 @@ pub struct Format {
215215
#[bpaf(external(color_detection), hide_usage)]
216216
pub color: bool,
217217

218-
/// Include full demangled name instead of just prefix
219-
#[bpaf(hide_usage)]
220-
pub full_name: bool,
218+
#[bpaf(hide_usage, external)]
219+
pub name_display: NameDisplay,
221220

222221
#[bpaf(external, hide_usage)]
223222
pub redundant_labels: RedundantLabels,
@@ -248,6 +247,22 @@ pub enum RedundantLabels {
248247
Strip,
249248
}
250249

250+
#[derive(Debug, Copy, Clone, Bpaf, Eq, PartialEq)]
251+
#[bpaf(fallback(NameDisplay::Short))]
252+
pub enum NameDisplay {
253+
#[bpaf(long("full-name"))]
254+
/// Include full demangled name instead of just prefix
255+
Full,
256+
257+
/// Include demangled names without hash suffix (default)
258+
#[bpaf(long("short-name"))]
259+
Short,
260+
261+
/// Do not demangle symbol names
262+
#[bpaf(long("keep-mangled"))]
263+
Mangled,
264+
}
265+
251266
#[derive(Debug, Clone, Bpaf, Eq, PartialEq, Copy)]
252267
#[bpaf(custom_usage(&[("OUTPUT-FORMAT", Style::Metavar)]), fallback(Syntax::Intel))]
253268
/// Pick output format:

0 commit comments

Comments
 (0)