From 5f5aa1123ab98b3f51edc89e814a8a3e3d13a012 Mon Sep 17 00:00:00 2001 From: Michael Baikov Date: Thu, 4 Apr 2024 08:51:58 -0400 Subject: [PATCH 1/7] URange - Range but with Copy and Ord --- src/lib.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 0b177a2..2db83b2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -290,3 +290,29 @@ pub fn dump_function(goal: ToDump, path: &Path, fmt: &Format) -> an }; Ok(()) } + +/// Mostly the same as Range, but Copy and Ord +#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq)] +pub struct URange { + start: usize, + end: usize, +} + +impl From> for URange { + fn from(Range { start, end }: Range) -> Self { + Self { start, end } + } +} + +impl std::ops::Index for [T] { + type Output = [T]; + fn index(&self, index: URange) -> &Self::Output { + &self[index.start..index.end] + } +} + +impl URange { + pub fn fully_contains(&self, other: Self) -> bool { + self.start >= other.start && self.end <= other.end + } +} From ba46608d515192fbe3f5e76d21ca38b4d13087bd Mon Sep 17 00:00:00 2001 From: Michael Baikov Date: Thu, 4 Apr 2024 08:58:04 -0400 Subject: [PATCH 2/7] When printing assembly instructions - include relevant constants --- src/asm.rs | 69 ++++++++++++++++++++++++++++++++++++++++++++----- src/demangle.rs | 2 +- 2 files changed, 64 insertions(+), 7 deletions(-) diff --git a/src/asm.rs b/src/asm.rs index 32a6f31..4fd285f 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -1,9 +1,10 @@ #![allow(clippy::missing_errors_doc)] -use crate::asm::statements::{GenericDirective, Label}; +use crate::asm::statements::{GenericDirective, Instruction, Label}; use crate::cached_lines::CachedLines; use crate::demangle::LabelKind; use crate::{ color, demangle, esafeprintln, get_context_for, get_dump_range, safeprintln, Item, RawLines, + URange, }; // TODO, use https://sourceware.org/binutils/docs/as/index.html use crate::opts::{Format, NameDisplay, RedundantLabels, SourcesFrom, ToDump}; @@ -196,13 +197,29 @@ fn used_labels<'a>(stmts: &'_ [Statement<'a>]) -> BTreeSet<&'a str> { .collect::>() } -pub fn dump_range( +/// Scans for referenced constants +fn scan_constant(name: &str, body: &[Statement]) -> Option { + let start = body.iter().position(|s| match s { + Statement::Directive(Directive::SectionStart(ss)) => ss.contains(name), + _ => false, + })?; + let end = body[start..] + .iter() + .position(|s| matches!(s, Statement::Nothing)) + .map_or_else(|| body.len(), |e| start + e); + Some(URange { start, end }) +} + +fn dump_range( files: &BTreeMap, fmt: &Format, - stmts: &[Statement], + print_range: Range, + body: &[Statement], // full body ) -> anyhow::Result<()> { + let print_range = URange::from(print_range); let mut prev_loc = Loc::default(); + let stmts = &body[print_range]; let used = if fmt.redundant_labels == RedundantLabels::Keep { BTreeSet::new() } else { @@ -290,6 +307,46 @@ pub fn dump_range( } } } + + // scan for referenced constants such as strings, scan needs to be done recursively + let mut pending = vec![print_range]; + let mut seen: BTreeSet = BTreeSet::new(); + + while let Some(subset) = pending.pop() { + seen.insert(subset); + for s in &body[subset] { + match s { + Statement::Instruction(Instruction { + args: Some(arg), .. + }) + | Statement::Directive(Directive::Generic(GenericDirective(arg))) => { + for label in crate::demangle::LOCAL_LABELS.find_iter(arg) { + let referenced_label = label.as_str().trim(); + if let Some(constant_range) = scan_constant(referenced_label, body) { + if !seen.contains(&constant_range) + && !print_range.fully_contains(constant_range) + { + pending.push(constant_range); + } + } + } + } + _ => (), + } + } + } + seen.remove(&print_range); + for range in &seen { + safeprintln!(""); + for line in &body[*range] { + match fmt.name_display { + NameDisplay::Full => safeprintln!("{line:#}"), + NameDisplay::Short => safeprintln!("{line}"), + NameDisplay::Mangled => safeprintln!("{line:-}"), + } + } + } + Ok(()) } @@ -500,21 +557,21 @@ pub fn dump_function( if let Some(range) = get_dump_range(goal, fmt, &functions) { let context = get_context_for(fmt.context, &statements[..], range.clone(), &functions); - dump_range(&files, fmt, &statements[range])?; + dump_range(&files, fmt, range, &statements)?; if !context.is_empty() { safeprintln!( "\n\n======================= Additional context =========================" ); for range in context { safeprintln!("\n"); - dump_range(&files, fmt, &statements[range])?; + dump_range(&files, fmt, range, &statements)?; } } } else { if fmt.verbosity > 0 { safeprintln!("Going to print the whole file"); } - dump_range(&files, fmt, &statements)?; + dump_range(&files, fmt, 0..statements.len(), &statements)?; } Ok(()) } diff --git a/src/demangle.rs b/src/demangle.rs index 74b9a56..5c1252d 100644 --- a/src/demangle.rs +++ b/src/demangle.rs @@ -44,7 +44,7 @@ const TEMP_LABELS_REGEX: &str = r"\b(Ltmp[0-9]+)\b"; static GLOBAL_LABELS: Lazy = Lazy::new(|| Regex::new(GLOBAL_LABELS_REGEX).expect("regexp should be valid")); -static LOCAL_LABELS: Lazy = +pub(crate) static LOCAL_LABELS: Lazy = Lazy::new(|| Regex::new(LOCAL_LABELS_REGEX).expect("regexp should be valid")); static LABEL_KINDS: Lazy = Lazy::new(|| { From 1a74bfe25ab46181628e9fe8148a78569b5bc59b Mon Sep 17 00:00:00 2001 From: Michael Baikov Date: Thu, 4 Apr 2024 09:10:28 -0400 Subject: [PATCH 3/7] Avoid repeatedly scanning for sections --- src/asm.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/asm.rs b/src/asm.rs index 4fd285f..27f87c5 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -198,11 +198,10 @@ fn used_labels<'a>(stmts: &'_ [Statement<'a>]) -> BTreeSet<&'a str> { } /// Scans for referenced constants -fn scan_constant(name: &str, body: &[Statement]) -> Option { - let start = body.iter().position(|s| match s { - Statement::Directive(Directive::SectionStart(ss)) => ss.contains(name), - _ => false, - })?; +fn scan_constant(name: &str, sections: &[(usize, &str)], body: &[Statement]) -> Option { + let start = sections + .iter() + .find_map(|(ix, ss)| ss.contains(name).then_some(*ix))?; let end = body[start..] .iter() .position(|s| matches!(s, Statement::Nothing)) @@ -312,6 +311,14 @@ fn dump_range( let mut pending = vec![print_range]; let mut seen: BTreeSet = BTreeSet::new(); + let sections = body + .iter() + .enumerate() + .filter_map(|(ix, stmt)| match stmt { + Statement::Directive(Directive::SectionStart(ss)) => Some((ix, *ss)), + _ => None, + }) + .collect::>(); while let Some(subset) = pending.pop() { seen.insert(subset); for s in &body[subset] { @@ -322,7 +329,9 @@ fn dump_range( | Statement::Directive(Directive::Generic(GenericDirective(arg))) => { for label in crate::demangle::LOCAL_LABELS.find_iter(arg) { let referenced_label = label.as_str().trim(); - if let Some(constant_range) = scan_constant(referenced_label, body) { + if let Some(constant_range) = + scan_constant(referenced_label, §ions, body) + { if !seen.contains(&constant_range) && !print_range.fully_contains(constant_range) { From 7a347eaddfe75731525ee727e2489cc4bd2fd71d Mon Sep 17 00:00:00 2001 From: Michael Baikov Date: Thu, 4 Apr 2024 09:16:44 -0400 Subject: [PATCH 4/7] Add an option to disable dumping constants --- README.md | 4 +++- src/asm.rs | 56 ++++++++++++++++++++++++++--------------------------- src/opts.rs | 4 ++++ 3 files changed, 35 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index d95199b..7bd86a5 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ $ cargo install cargo-show-asm Show the code rustc generates for any function -**Usage**: **`cargo asm`** \[**`-p`**=_`SPEC`_\] \[_`ARTIFACT`_\] \[**`-M`**=_`ARG`_\]... \[_`TARGET-CPU`_\] \[**`--rust`**\] \[**`-c`**=_`COUNT`_\] \[**`--simplify`**\] \[**`--this-workspace`** | **`--all-crates`** | **`--all-sources`**\] \[_`OUTPUT-FORMAT`_\] \[**`--everything`** | _`FUNCTION`_ \[_`INDEX`_\]\] +**Usage**: **`cargo asm`** \[**`-p`**=_`SPEC`_\] \[_`ARTIFACT`_\] \[**`-M`**=_`ARG`_\]... \[_`TARGET-CPU`_\] \[**`--rust`**\] \[**`-c`**=_`COUNT`_\] \[**`--simplify`**\] \[**`--no-constants`**\] \[**`--this-workspace`** | **`--all-crates`** | **`--all-sources`**\] \[_`OUTPUT-FORMAT`_\] \[**`--everything`** | _`FUNCTION`_ \[_`INDEX`_\]\] Usage: 1. Focus on a single assembly producing target: @@ -133,6 +133,8 @@ Show the code rustc generates for any function more verbose output, can be specified multiple times - **` --simplify`** — Try to strip some of the non-assembly instruction information +- **` --no-constants`** — + Don't detect/include sections containing string literals and other constants - **`-b`**, **`--keep-blank`** — Keep blank lines - **` --this-workspace`** — diff --git a/src/asm.rs b/src/asm.rs index 27f87c5..86f7539 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -307,26 +307,27 @@ fn dump_range( } } - // scan for referenced constants such as strings, scan needs to be done recursively - let mut pending = vec![print_range]; - let mut seen: BTreeSet = BTreeSet::new(); - - let sections = body - .iter() - .enumerate() - .filter_map(|(ix, stmt)| match stmt { - Statement::Directive(Directive::SectionStart(ss)) => Some((ix, *ss)), - _ => None, - }) - .collect::>(); - while let Some(subset) = pending.pop() { - seen.insert(subset); - for s in &body[subset] { - match s { - Statement::Instruction(Instruction { + if fmt.include_constants { + // scan for referenced constants such as strings, scan needs to be done recursively + let mut pending = vec![print_range]; + let mut seen: BTreeSet = BTreeSet::new(); + + let sections = body + .iter() + .enumerate() + .filter_map(|(ix, stmt)| match stmt { + Statement::Directive(Directive::SectionStart(ss)) => Some((ix, *ss)), + _ => None, + }) + .collect::>(); + while let Some(subset) = pending.pop() { + seen.insert(subset); + for s in &body[subset] { + if let Statement::Instruction(Instruction { args: Some(arg), .. }) - | Statement::Directive(Directive::Generic(GenericDirective(arg))) => { + | Statement::Directive(Directive::Generic(GenericDirective(arg))) = s + { for label in crate::demangle::LOCAL_LABELS.find_iter(arg) { let referenced_label = label.as_str().trim(); if let Some(constant_range) = @@ -340,18 +341,17 @@ fn dump_range( } } } - _ => (), } } - } - seen.remove(&print_range); - for range in &seen { - safeprintln!(""); - for line in &body[*range] { - match fmt.name_display { - NameDisplay::Full => safeprintln!("{line:#}"), - NameDisplay::Short => safeprintln!("{line}"), - NameDisplay::Mangled => safeprintln!("{line:-}"), + seen.remove(&print_range); + for range in &seen { + safeprintln!(""); + for line in &body[*range] { + match fmt.name_display { + NameDisplay::Full => safeprintln!("{line:#}"), + NameDisplay::Short => safeprintln!("{line}"), + NameDisplay::Mangled => safeprintln!("{line:-}"), + } } } } diff --git a/src/opts.rs b/src/opts.rs index 6a478a6..eed3a4c 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -232,6 +232,10 @@ pub struct Format { /// Try to strip some of the non-assembly instruction information pub simplify: bool, + /// Don't detect/include sections containing string literals and other constants + #[bpaf(long("no-constants"), flag(false, true))] + pub include_constants: bool, + /// Keep blank lines #[bpaf(short('b'), long, hide_usage)] pub keep_blank: bool, From e53fac79988b65f30d2596cc7cba519176407981 Mon Sep 17 00:00:00 2001 From: Michael Baikov Date: Thu, 4 Apr 2024 09:19:51 -0400 Subject: [PATCH 5/7] sample: clean up warnings, add a panicking function --- sample/src/lib.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sample/src/lib.rs b/sample/src/lib.rs index c53dfc4..f9470ce 100644 --- a/sample/src/lib.rs +++ b/sample/src/lib.rs @@ -32,7 +32,12 @@ pub fn main() -> u32 { 1 + 1 } -pub struct Bar(u32); +#[inline(never)] +pub fn panics() { + panic!("oh noes asdf wef wef wf wefwefwef wef! {}", "bob"); +} + +pub struct Bar(pub u32); impl Bar { #[no_mangle] pub fn make_bar(a: u32, b: u32) -> Self { From 2e7be7f4cb6f0e533222fd8cb7ab2e288993bef7 Mon Sep 17 00:00:00 2001 From: Michael Baikov Date: Thu, 4 Apr 2024 09:11:28 -0400 Subject: [PATCH 6/7] Disable some more features for release-plz --- release-plz.toml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/release-plz.toml b/release-plz.toml index 903bbcf..d190014 100644 --- a/release-plz.toml +++ b/release-plz.toml @@ -1,12 +1,10 @@ [workspace] -# path of the git-cliff configuration -changelog_config = "cliff.toml" # enable changelog updates -changelog_update = true +changelog_update = false # update dependencies with `cargo update` -dependencies_update = true +dependencies_update = false # create tags for the releases git_tag_enable = true @@ -24,4 +22,4 @@ allow_dirty = false publish_allow_dirty = false # disable running `cargo-semver-checks` -semver_check = false \ No newline at end of file +semver_check = false From c725fe2aaed3cf948920b8c4f2ba0bcca3a3d6ba Mon Sep 17 00:00:00 2001 From: Michael Baikov Date: Thu, 4 Apr 2024 09:22:30 -0400 Subject: [PATCH 7/7] Update changelog --- Changelog.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Changelog.md b/Changelog.md index c0a5f62..e08a36a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,10 @@ # Change Log +## [0.2.31] - 2024-04-04 +- include relevant constants in produced asm output + this can be disabled with `--no-constants` +- bump deps + ## [0.2.30] - 2024-02-11 - Add an option `-c` / `--context` to recursively include functions called from target as additional context