diff --git a/.github/workflows/check-and-lint.yaml b/.github/workflows/check-and-lint.yaml index e692716..e8f1e4d 100644 --- a/.github/workflows/check-and-lint.yaml +++ b/.github/workflows/check-and-lint.yaml @@ -32,134 +32,7 @@ jobs: run: cargo fmt --all --check - name: Native version of cargo-show-asm (Intel ASM) - run: cargo run -- --manifest-path sample/Cargo.toml --intel sample::main --rust - - - name: Native version of cargo-show-asm (Intel ASM) + native CPU - run: cargo run -- --manifest-path sample/Cargo.toml --native --intel sample::main --rust - - - name: Native version of cargo-show-asm (Intel ASM) + native CPU + no default features - run: cargo run -- -vvv --manifest-path sample/Cargo.toml --native --intel sample::main --rust --no-default-features - - - name: Native version of cargo-show-asm (Intel ASM) + atom - run: cargo run -- --manifest-path sample/Cargo.toml --target-cpu atom --intel sample::main --rust - - - name: Native version of cargo-show-asm with symbol mangling (Intel ASM) - run: cargo run -- --manifest-path sample/Cargo.toml --intel sample::main --rust --keep-mangled - - - name: Native version of cargo-show-asm (LLVM) - run: cargo run -- --manifest-path sample/Cargo.toml --llvm sample::main - - - name: Native version of cargo-show-asm with symbol mangling (LLVM) - run: cargo run -- --manifest-path sample/Cargo.toml --llvm --keep-mangled sample::main - - - name: Native version of cargo-show-asm (LLVM Input) - run: cargo run -- --manifest-path sample/Cargo.toml --llvm-input sample::main - - - name: Native version of cargo-show-asm (MIR) - run: cargo run -- --manifest-path sample/Cargo.toml --mir "main()" - - - name: Crosscompiled version of cargo-show-asm (Intel ASM) - run: cargo run -- --manifest-path sample/Cargo.toml --intel sample::main --target armv7-unknown-linux-gnueabihf - - - name: Rlib project, AT&T asm - run: cargo run -- --manifest-path sample_rlib/Cargo.toml --att - - - name: cdylib project - run: cargo run -- --manifest-path sample_cdylib/Cargo.toml add - - - name: cdylib project, underscore prefix - run: cargo run -- --manifest-path sample_cdylib/Cargo.toml _mul - - windows: - runs-on: windows-latest - name: Tests on windows - steps: - - name: Checkout repo - uses: actions/checkout@v3 - - - name: Install rust toolchain - uses: dtolnay/rust-toolchain@stable - with: - toolchain: stable - components: rustfmt clippy rust-src - targets: armv7-unknown-linux-gnueabihf - - - name: Build all the things - run: cargo build --tests - - - name: Run unit tests - run: cargo test --all-features - - - name: Clippy - run: cargo clippy -- -D clippy::disallowed_macros - - - name: Check formatting - run: cargo fmt --all --check - - - name: Native version of cargo-show-asm (Intel ASM) - run: cargo run -- --manifest-path sample/Cargo.toml --intel sample::main --rust - - - name: Native version of cargo-show-asm (Intel ASM) + native CPU - run: cargo run -- --manifest-path sample/Cargo.toml --native --intel sample::main --rust - - - name: Native version of cargo-show-asm (Intel ASM) + native CPU + no default features - run: cargo run -- -vvv --manifest-path sample/Cargo.toml --native --intel sample::main --rust --no-default-features - - - name: Native version of cargo-show-asm (Intel ASM) + atom - run: cargo run -- --manifest-path sample/Cargo.toml --target-cpu atom --intel sample::main --rust - - - name: Native version of cargo-show-asm with symbol mangling (Intel ASM) - run: cargo run -- --manifest-path sample/Cargo.toml --intel sample::main --rust --keep-mangled - - - name: Native version of cargo-show-asm (LLVM) - run: cargo run -- --manifest-path sample/Cargo.toml --llvm sample::main - - - name: Native version of cargo-show-asm with symbol mangling (LLVM) - run: cargo run -- --manifest-path sample/Cargo.toml --llvm --keep-mangled sample::main - - - name: Native version of cargo-show-asm (LLVM Input) - run: cargo run -- --manifest-path sample/Cargo.toml --llvm-input sample::main - - - name: Native version of cargo-show-asm (MIR) - run: cargo run -- --manifest-path sample/Cargo.toml --mir "main()" - - - name: Crosscompiled version of cargo-show-asm (Intel ASM) - run: cargo run -- --manifest-path sample/Cargo.toml --intel sample::main --target armv7-unknown-linux-gnueabihf - - - name: Rlib project, AT&T asm - run: cargo run -- --manifest-path sample_rlib/Cargo.toml --att - - - name: cdylib project - run: cargo run -- --manifest-path sample_cdylib/Cargo.toml --everything - - macos: - runs-on: macos-latest - name: Tests on MacOS - steps: - - name: Checkout repo - uses: actions/checkout@v3 - - - name: Install rust toolchain - uses: dtolnay/rust-toolchain@stable - with: - toolchain: stable - components: rustfmt clippy rust-src - targets: armv7-unknown-linux-gnueabihf - - - name: Build all the things - run: cargo build --tests - - - name: Run unit tests - run: cargo test --all-features - - - name: Clippy - run: cargo clippy -- -D clippy::disallowed_macros - - - name: Check formatting - run: cargo fmt --all --check - - - name: Native version of cargo-show-asm (Intel ASM) - run: cargo run -- --manifest-path sample/Cargo.toml --intel sample::main --rust + run: cargo run -- -vvv --manifest-path sample/Cargo.toml --intel sample::main --rust - name: Native version of cargo-show-asm (Intel ASM) + native CPU run: cargo run -- --manifest-path sample/Cargo.toml --native --intel sample::main --rust @@ -196,3 +69,130 @@ jobs: - name: cdylib project, underscore prefix run: cargo run -- --manifest-path sample_cdylib/Cargo.toml _mul +# +# windows: +# runs-on: windows-latest +# name: Tests on windows +# steps: +# - name: Checkout repo +# uses: actions/checkout@v3 +# +# - name: Install rust toolchain +# uses: dtolnay/rust-toolchain@stable +# with: +# toolchain: stable +# components: rustfmt clippy rust-src +# targets: armv7-unknown-linux-gnueabihf +# +# - name: Build all the things +# run: cargo build --tests +# +# - name: Run unit tests +# run: cargo test --all-features +# +# - name: Clippy +# run: cargo clippy -- -D clippy::disallowed_macros +# +# - name: Check formatting +# run: cargo fmt --all --check +# +# - name: Native version of cargo-show-asm (Intel ASM) +# run: cargo run -- --manifest-path sample/Cargo.toml --intel sample::main --rust +# +# - name: Native version of cargo-show-asm (Intel ASM) + native CPU +# run: cargo run -- --manifest-path sample/Cargo.toml --native --intel sample::main --rust +# +# - name: Native version of cargo-show-asm (Intel ASM) + native CPU + no default features +# run: cargo run -- -vvv --manifest-path sample/Cargo.toml --native --intel sample::main --rust --no-default-features +# +# - name: Native version of cargo-show-asm (Intel ASM) + atom +# run: cargo run -- --manifest-path sample/Cargo.toml --target-cpu atom --intel sample::main --rust +# +# - name: Native version of cargo-show-asm with symbol mangling (Intel ASM) +# run: cargo run -- --manifest-path sample/Cargo.toml --intel sample::main --rust --keep-mangled +# +# - name: Native version of cargo-show-asm (LLVM) +# run: cargo run -- --manifest-path sample/Cargo.toml --llvm sample::main +# +# - name: Native version of cargo-show-asm with symbol mangling (LLVM) +# run: cargo run -- --manifest-path sample/Cargo.toml --llvm --keep-mangled sample::main +# +# - name: Native version of cargo-show-asm (LLVM Input) +# run: cargo run -- --manifest-path sample/Cargo.toml --llvm-input sample::main +# +# - name: Native version of cargo-show-asm (MIR) +# run: cargo run -- --manifest-path sample/Cargo.toml --mir "main()" +# +# - name: Crosscompiled version of cargo-show-asm (Intel ASM) +# run: cargo run -- --manifest-path sample/Cargo.toml --intel sample::main --target armv7-unknown-linux-gnueabihf +# +# - name: Rlib project, AT&T asm +# run: cargo run -- --manifest-path sample_rlib/Cargo.toml --att +# +# - name: cdylib project +# run: cargo run -- --manifest-path sample_cdylib/Cargo.toml --everything +# +# macos: +# runs-on: macos-latest +# name: Tests on MacOS +# steps: +# - name: Checkout repo +# uses: actions/checkout@v3 +# +# - name: Install rust toolchain +# uses: dtolnay/rust-toolchain@stable +# with: +# toolchain: stable +# components: rustfmt clippy rust-src +# targets: armv7-unknown-linux-gnueabihf +# +# - name: Build all the things +# run: cargo build --tests +# +# - name: Run unit tests +# run: cargo test --all-features +# +# - name: Clippy +# run: cargo clippy -- -D clippy::disallowed_macros +# +# - name: Check formatting +# run: cargo fmt --all --check +# +# - name: Native version of cargo-show-asm (Intel ASM) +# run: cargo run -- --manifest-path sample/Cargo.toml --intel sample::main --rust +# +# - name: Native version of cargo-show-asm (Intel ASM) + native CPU +# run: cargo run -- --manifest-path sample/Cargo.toml --native --intel sample::main --rust +# +# - name: Native version of cargo-show-asm (Intel ASM) + native CPU + no default features +# run: cargo run -- -vvv --manifest-path sample/Cargo.toml --native --intel sample::main --rust --no-default-features +# +# - name: Native version of cargo-show-asm (Intel ASM) + atom +# run: cargo run -- --manifest-path sample/Cargo.toml --target-cpu atom --intel sample::main --rust +# +# - name: Native version of cargo-show-asm with symbol mangling (Intel ASM) +# run: cargo run -- --manifest-path sample/Cargo.toml --intel sample::main --rust --keep-mangled +# +# - name: Native version of cargo-show-asm (LLVM) +# run: cargo run -- --manifest-path sample/Cargo.toml --llvm sample::main +# +# - name: Native version of cargo-show-asm with symbol mangling (LLVM) +# run: cargo run -- --manifest-path sample/Cargo.toml --llvm --keep-mangled sample::main +# +# - name: Native version of cargo-show-asm (LLVM Input) +# run: cargo run -- --manifest-path sample/Cargo.toml --llvm-input sample::main +# +# - name: Native version of cargo-show-asm (MIR) +# run: cargo run -- --manifest-path sample/Cargo.toml --mir "main()" +# +# - name: Crosscompiled version of cargo-show-asm (Intel ASM) +# run: cargo run -- --manifest-path sample/Cargo.toml --intel sample::main --target armv7-unknown-linux-gnueabihf +# +# - name: Rlib project, AT&T asm +# run: cargo run -- --manifest-path sample_rlib/Cargo.toml --att +# +# - name: cdylib project +# run: cargo run -- --manifest-path sample_cdylib/Cargo.toml add +# +# - name: cdylib project, underscore prefix +# run: cargo run -- --manifest-path sample_cdylib/Cargo.toml _mul diff --git a/Cargo.lock b/Cargo.lock index 64a7dd5..9886164 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,12 @@ version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" +[[package]] +name = "ar" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d67af77d68a931ecd5cbd8a3b5987d63a1d1d1278f7f6a60ae33db485cdebb69" + [[package]] name = "bitflags" version = "2.4.2" @@ -68,6 +74,7 @@ name = "cargo-show-asm" version = "0.2.30" dependencies = [ "anyhow", + "ar", "bpaf", "cargo_metadata", "line-span", diff --git a/Cargo.toml b/Cargo.toml index 3757924..773b34c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ rustc-demangle = "0.1" same-file = "1.0.6" supports-color = "3.0" serde = "=1.0.195" +ar = "0.9.0" [dev-dependencies] bpaf = { version = "0.9.8", features = ["bpaf_derive", "autocomplete", "docgen"] } diff --git a/Changelog.md b/Changelog.md index c0a5f62..d954750 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,8 @@ # Change Log +## [0.2.31] - unreleased +- replace RPITIT with more consevative implementation + ## [0.2.30] - 2024-02-11 - Add an option `-c` / `--context` to recursively include functions called from target as additional context diff --git a/src/asm.rs b/src/asm.rs index 32a6f31..375e9a1 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -473,7 +473,7 @@ impl RawLines for Statement<'_> { /// try to print `goal` from `path`, collect available items otherwise pub fn dump_function( goal: ToDump, - path: &Path, + contents: String, workspace: &Path, sysroot: &Path, fmt: &Format, @@ -483,8 +483,6 @@ pub fn dump_function( } // For some reason llvm/rustc can produce non utf8 files... - let payload = std::fs::read(path)?; - let contents = String::from_utf8_lossy(&payload).into_owned(); let statements = parse_file(&contents)?; let functions = find_items(&statements); diff --git a/src/lib.rs b/src/lib.rs index 0b177a2..6f61161 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,7 +7,6 @@ use std::{ use crate::cached_lines::CachedLines; use opts::{Format, NameDisplay, ToDump}; -use std::path::Path; pub mod asm; pub mod cached_lines; @@ -16,6 +15,7 @@ pub mod llvm; pub mod mca; pub mod mir; pub mod opts; +pub mod rlib; #[macro_export] macro_rules! color { @@ -265,10 +265,11 @@ pub trait Dumpable { /// /// # Errors /// Reports file IO errors -pub fn dump_function(goal: ToDump, path: &Path, fmt: &Format) -> anyhow::Result<()> { - // For some reason llvm/rustc can produce non utf8 files... - let payload = std::fs::read(path)?; - let contents = String::from_utf8_lossy(&payload).into_owned(); +pub fn dump_function( + goal: ToDump, + contents: String, + fmt: &Format, +) -> anyhow::Result<()> { let lines = CachedLines::without_ending(contents); let items = T::find_items(&lines); let strs = lines.iter().collect::>(); diff --git a/src/main.rs b/src/main.rs index 6f75590..6727bd7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,8 @@ use anyhow::Context; use cargo_metadata::{Artifact, Message, MetadataCommand, Package}; -use cargo_show_asm::dump_function; -use cargo_show_asm::llvm::Llvm; -use cargo_show_asm::mir::Mir; -use cargo_show_asm::{asm, esafeprintln, mca, opts}; +use cargo_show_asm::{ + asm, dump_function, esafeprintln, llvm::Llvm, mca, mir::Mir, opts, rlib::artifact_byproducts, +}; use once_cell::sync::Lazy; use std::{ io::BufReader, @@ -231,22 +230,25 @@ fn main() -> anyhow::Result<()> { esafeprintln!("Artifact files: {:?}", artifact.filenames); } - let asm_path = locate_asm_path_via_artifact(&artifact, opts.syntax.ext())?; + let byproducts = artifact_byproducts(&artifact, opts.syntax.ext(), opts.format.verbosity)?; + + // let asm_path = locate_asm_path_via_artifact(&artifact, opts.syntax.ext())?; if opts.format.verbosity > 0 { - esafeprintln!("Asm file: {}", asm_path.display()); + // esafeprintln!("Asm file: {}", asm_path.display()); } + let contents = cargo_show_asm::rlib::read_files(&byproducts)?; match opts.syntax { Syntax::Intel | Syntax::Att | Syntax::Wasm => asm::dump_function( opts.to_dump, - &asm_path, + contents, metadata.workspace_root.as_std_path(), &sysroot, &opts.format, ), Syntax::McaAtt | Syntax::McaIntel => mca::dump_function( opts.to_dump, - &asm_path, + contents, &opts.format, &opts.mca_arg, opts.syntax == Syntax::McaIntel, @@ -254,9 +256,9 @@ fn main() -> anyhow::Result<()> { &opts.target_cpu, ), Syntax::Llvm | Syntax::LlvmInput => { - dump_function::(opts.to_dump, &asm_path, &opts.format) + dump_function::(opts.to_dump, contents, &opts.format) } - Syntax::Mir => dump_function::(opts.to_dump, &asm_path, &opts.format), + Syntax::Mir => dump_function::(opts.to_dump, contents, &opts.format), } } diff --git a/src/mca.rs b/src/mca.rs index fe1a36d..8e5501b 100644 --- a/src/mca.rs +++ b/src/mca.rs @@ -1,6 +1,5 @@ use std::{ io::{BufRead, BufReader}, - path::Path, process::{Command, Stdio}, }; @@ -16,7 +15,7 @@ use crate::{ /// Clippy, why do you care? pub fn dump_function( goal: ToDump, - path: &Path, + contents: String, fmt: &Format, mca_args: &[String], mca_intel: bool, @@ -25,10 +24,6 @@ pub fn dump_function( ) -> anyhow::Result<()> { use std::io::Write; - // For some reason llvm/rustc can produce non utf8 files... - let payload = std::fs::read(path)?; - let contents = String::from_utf8_lossy(&payload).into_owned(); - let statements = crate::asm::parse_file(&contents)?; let functions = crate::asm::find_items(&statements); diff --git a/src/rlib.rs b/src/rlib.rs new file mode 100644 index 0000000..38113df --- /dev/null +++ b/src/rlib.rs @@ -0,0 +1,114 @@ +use crate::esafeprintln; +use ar::Archive; +use cargo_metadata::Artifact; +use std::{ + fs::File, + path::{Path, PathBuf}, +}; + +pub fn artifact_byproducts( + artifact: &Artifact, + ext: &str, + verbosity: usize, +) -> anyhow::Result> { + for file in artifact.filenames.iter() { + if file.extension() == Some("rlib") { + return locate_byproducts(file, ext, verbosity); + } + } + anyhow::bail!("no rmeta?"); +} + +/// Look inside of rlib file to figure out artifact names +/// +/// rlib files are ar archives [1] and contain object code generated by compiler. multiple +/// compilation units we can abuse names of the object files to get names of emitted byproducts: +/// +/// sample-7aab9f7e7ab26e00.53xe9n61hxojleor.rcgu.o => +/// sample-7aab9f7e7ab26e00.53xe9n61hxojleor.rcgu.s +/// +/// This is needed so we can tell which files were generated +/// +/// - [1] https://rustc-dev-guide.rust-lang.org/backend/libs-and-metadata.html +pub fn locate_byproducts( + rlib: impl AsRef, + ext: &str, + verbosity: usize, +) -> anyhow::Result> { + let mut res = Vec::new(); + let rlib = rlib.as_ref(); + let mut archive = Archive::new(File::open(rlib).unwrap()); + + let basedir = rlib + .parent() + .ok_or_else(|| anyhow::anyhow!("Can't get a folder of {rlib:?}"))? + .join("deps"); + + if verbosity > 2 { + esafeprintln!("Base dir with source files is {basedir:?}"); + } + + let mut missing = Vec::new(); + while let Some(entry) = archive.next_entry() { + let entry = entry?; + let name = std::str::from_utf8(entry.header().identifier())?; + if name == "lib.rmeta" { + continue; + } + + let mut file = basedir.join(name); + file.set_extension(ext); + if file.exists() { + if verbosity > 2 { + esafeprintln!("Found a byproduct {file:?}"); + } + res.push(file) + } else { + esafeprintln!("Expected byproduct {file:?} doesn't exist"); + missing.push(file); + } + } + if !res.is_empty() && missing.is_empty() { + for file in &missing { + esafeprintln!("A byproduct is supposed to be located at {file:?}, but it's missing"); + } + } + + if missing.len() == 1 && res.is_empty() { + if verbosity > 1 { + esafeprintln!("Converting {:?} to a single byproduct", missing[0]); + } + assert_eq!(missing[0].extension().unwrap(), ext); + let mut singleton = missing.remove(0); + if verbosity > 2 { + esafeprintln!("Going to strip extensions from {singleton:?}"); + } + while singleton.extension().is_some() { + singleton = singleton.with_extension(""); + } + + let singleton = singleton.with_extension(ext); + if singleton.exists() { + return Ok(vec![singleton]); + } else { + for f in basedir.read_dir()? { + let f = f.unwrap(); + crate::safeprintln!("- {:?}", f.file_name()); + } + anyhow::bail!("Expected to find a single byproduct file at {singleton:?}, it doesn't exist there either"); + } + } + + Ok(res) +} + +pub fn read_files(paths: &[PathBuf]) -> anyhow::Result { + let mut res = String::new(); + + for file in paths { + res += &String::from_utf8_lossy(&std::fs::read(file)?); + res += "\n"; + } + + Ok(res) +}