Skip to content

Commit

Permalink
Use sysroot so that we can display rust sources in backtraces
Browse files Browse the repository at this point in the history
  • Loading branch information
davidlattimore committed Sep 20, 2023
1 parent c852ef2 commit e8dbc0c
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 7 deletions.
4 changes: 4 additions & 0 deletions src/checker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ pub(crate) struct Checker {
tmpdir: Arc<TempDir>,
pub(crate) args: Arc<Args>,
pub(crate) crate_index: Arc<CrateIndex>,
pub(crate) sysroot: Arc<Path>,

/// Mapping from Rust source paths to the packages that contains them. Generally a source path
/// will map to a single package, but in rare cases multiple packages could reference the same
Expand Down Expand Up @@ -105,6 +106,7 @@ impl Checker {
tmpdir: Arc<TempDir>,
target_dir: PathBuf,
args: Arc<Args>,
sysroot: Arc<Path>,
crate_index: Arc<CrateIndex>,
config_path: PathBuf,
) -> Self {
Expand All @@ -122,6 +124,7 @@ impl Checker {
timings,
backtracers: Default::default(),
outstanding_linker_invocations: Default::default(),
sysroot,
}
}

Expand Down Expand Up @@ -577,6 +580,7 @@ mod tests {
Arc::new(TempDir::new(None).unwrap()),
PathBuf::default(),
Arc::new(Args::default()),
Arc::from(Path::new("")),
Arc::new(CrateIndex::default()),
PathBuf::default(),
)
Expand Down
13 changes: 13 additions & 0 deletions src/location.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,19 @@ impl SourceLocation {
pub(crate) fn column(&self) -> Option<u32> {
self.column
}

pub(crate) fn with_sysroot(&self, sysroot: &Path) -> Self {
if !self.filename.starts_with("/rustc/") {
return self.clone();
}
let mut filename = sysroot.join("lib/rustlib/src/rust");
filename.extend(self.filename.iter().skip(3));
Self {
filename: Arc::from(filename.as_path()),
line: self.line,
column: self.column,
}
}
}

impl Display for SourceLocation {
Expand Down
22 changes: 18 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ mod tmpdir;
mod ui;
mod unsafe_checker;

use crate::proxy::subprocess::PROXY_BIN_ARG;
use anyhow::anyhow;
use anyhow::bail;
use anyhow::Context;
use anyhow::Result;
use checker::Checker;
use clap::builder::OsStr;
use clap::Parser;
use clap::Subcommand;
use crate_index::CrateIndex;
Expand All @@ -61,8 +61,6 @@ use std::sync::Mutex;
use std::thread::JoinHandle;
use summary::SummaryOptions;
use symbol_graph::ScanOutputs;

use crate::proxy::subprocess::PROXY_BIN_ARG;
use tmpdir::TempDir;

#[derive(Parser, Debug, Clone, Default)]
Expand Down Expand Up @@ -163,7 +161,11 @@ pub(crate) struct ProxyBinOptions {
fn main() -> Result<()> {
proxy::subprocess::handle_wrapped_binaries()?;

if std::env::args_os().nth(1).as_deref() == Some(&OsStr::from(PROXY_BIN_ARG)) {
if std::env::args_os()
.nth(1)
.map(|arg| arg == PROXY_BIN_ARG)
.unwrap_or(false)
{
// If we get here and the call to handle_wrapped_binaries above didn't diverge, then either
// a user invoked a bin wrapper directly, or we've been invoked when we're already inside a
// cackle sandbox. In either case, we just run the original binary directly.
Expand Down Expand Up @@ -219,6 +221,7 @@ impl Cackle {
tmpdir.clone(),
target_dir.clone(),
args.clone(),
determine_sysroot(&root_path)?,
crate_index.clone(),
config_path.clone(),
)));
Expand Down Expand Up @@ -447,6 +450,17 @@ impl Cackle {
}
}

fn determine_sysroot(root_path: &PathBuf) -> Result<Arc<Path>> {
let output = std::process::Command::new("rustc")
.current_dir(root_path)
.arg("--print")
.arg("sysroot")
.output()
.context("Failed to run `rustc --print sysroot`")?;
let stdout = std::str::from_utf8(&output.stdout).context("rust sysroot isn't UTF-8")?;
Ok(Arc::from(Path::new(stdout.trim())))
}

#[derive(Default)]
struct CheckState {
graph_outputs: Option<ScanOutputs>,
Expand Down
2 changes: 1 addition & 1 deletion src/symbol_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ pub(crate) fn scan_objects(
.with_context(|| format!("Failed to read `{}`", link_info.output_file.display()))?;
checker.timings.add_timing(start, "Read bin file");

let mut backtracer = Backtracer::default();
let mut backtracer = Backtracer::new(checker.sysroot.clone());
let outputs =
scan_object_with_bin_bytes(&file_bytes, checker, &mut backtracer, link_info, paths)?;

Expand Down
16 changes: 14 additions & 2 deletions src/symbol_graph/backtrace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ use fxhash::FxHashMap;
use fxhash::FxHashSet;
use gimli::Dwarf;
use std::fmt::Display;
use std::path::Path;
use std::sync::Arc;

#[derive(Default)]
pub(crate) struct Backtracer {
/// A map from symbol addresses in the binary to a list of relocations pointing to that address.
back_references: FxHashMap<u64, Vec<BinLocation>>,

bin_bytes: Vec<u8>,

sysroot: Arc<Path>,
}

#[derive(Debug, PartialEq, Eq)]
Expand All @@ -23,6 +26,14 @@ pub(crate) struct Frame {
}

impl Backtracer {
pub(crate) fn new(sysroot: Arc<Path>) -> Self {
Self {
sysroot,
back_references: Default::default(),
bin_bytes: Default::default(),
}
}

/// Declare a reference from `bin_location` to `target_address`.
pub(crate) fn add_reference(&mut self, bin_location: BinLocation, target_address: u64) {
self.back_references
Expand Down Expand Up @@ -68,7 +79,8 @@ impl Backtracer {
.unwrap_or_else(|| "??".to_owned());
let source_location = frame
.location
.and_then(|location| SourceLocation::try_from(&location).ok());
.and_then(|location| SourceLocation::try_from(&location).ok())
.map(|location| location.with_sysroot(&self.sysroot));
if first {
first = false;
} else {
Expand Down

0 comments on commit e8dbc0c

Please sign in to comment.