Skip to content

Commit

Permalink
Add hash of source files in debug info
Browse files Browse the repository at this point in the history
* Adds either an MD5 or SHA1 hash to the debug info.
* Adds new unstable option `-Z src-hash-algorithm` to control the hashing algorithm.
  • Loading branch information
arlosi committed Apr 2, 2020
1 parent 537ccdf commit f86b078
Show file tree
Hide file tree
Showing 19 changed files with 332 additions and 92 deletions.
64 changes: 44 additions & 20 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,6 @@ dependencies = [
"scoped_threadpool",
]

[[package]]
name = "arrayref"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"

[[package]]
name = "arrayvec"
version = "0.4.7"
Expand Down Expand Up @@ -187,11 +181,22 @@ dependencies = [

[[package]]
name = "block-buffer"
version = "0.3.3"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
dependencies = [
"block-padding",
"byte-tools",
"byteorder",
"generic-array",
]

[[package]]
name = "block-padding"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab"
checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
dependencies = [
"arrayref",
"byte-tools",
]

Expand Down Expand Up @@ -240,9 +245,9 @@ version = "0.1.0"

[[package]]
name = "byte-tools"
version = "0.2.0"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"

[[package]]
name = "bytecount"
Expand Down Expand Up @@ -897,9 +902,9 @@ checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"

[[package]]
name = "digest"
version = "0.7.6"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
dependencies = [
"generic-array",
]
Expand Down Expand Up @@ -1226,9 +1231,9 @@ dependencies = [

[[package]]
name = "generic-array"
version = "0.9.0"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d"
checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
dependencies = [
"typenum",
]
Expand Down Expand Up @@ -1962,6 +1967,17 @@ version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"

[[package]]
name = "md-5"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a18af3dcaf2b0219366cdb4e2af65a6101457b415c3d1a5c71dd9c2b7c77b9c8"
dependencies = [
"block-buffer",
"digest",
"opaque-debug",
]

[[package]]
name = "mdbook"
version = "0.3.5"
Expand Down Expand Up @@ -2250,6 +2266,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6a04cb71e910d0034815600180f62a95bf6e67942d7ab52a166a68c7d7e9cd0"

[[package]]
name = "opaque-debug"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"

[[package]]
name = "open"
version = "1.2.1"
Expand Down Expand Up @@ -2467,9 +2489,9 @@ dependencies = [

[[package]]
name = "pest_meta"
version = "2.1.0"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5a3492a4ed208ffc247adcdcc7ba2a95be3104f58877d0d02f0df39bf3efb5e"
checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d"
dependencies = [
"maplit",
"pest",
Expand Down Expand Up @@ -4155,11 +4177,13 @@ dependencies = [
"arena",
"cfg-if",
"log",
"md-5",
"rustc_data_structures",
"rustc_index",
"rustc_macros",
"scoped-tls",
"serialize",
"sha-1",
"unicode-width",
]

Expand Down Expand Up @@ -4535,14 +4559,14 @@ dependencies = [

[[package]]
name = "sha-1"
version = "0.7.0"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9d1f3b5de8a167ab06834a7c883bd197f2191e1dda1a22d9ccfeedbf9aded"
checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
dependencies = [
"block-buffer",
"byte-tools",
"digest",
"fake-simd",
"opaque-debug",
]

[[package]]
Expand Down
11 changes: 11 additions & 0 deletions src/doc/unstable-book/src/compiler-flags/src-hash-algorithm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# `src-hash-algorithm`

The tracking issue for this feature is: [#70401](https://github.com/rust-lang/rust/issues/70401).

------------------------

The `-Z src-hash-algorithm` compiler flag controls which algorithm is used when hashing each source file. The hash is stored in the debug info and can be used by a debugger to verify the source code matches the executable.

Supported hash algorithms are: `md5`, and `sha1`. Note that not all hash algorithms are supported by all debug info formats.

By default, the compiler chooses the hash algorithm based on the target specification.
34 changes: 31 additions & 3 deletions src/librustc_codegen_llvm/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ use rustc_middle::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_session::config::{self, DebugInfo};
use rustc_span::symbol::{Interner, Symbol};
use rustc_span::{self, FileName, Span};
use rustc_span::{self, FileName, SourceFileHash, Span};
use rustc_target::abi::{Abi, Align, DiscriminantKind, HasDataLayout, Integer, LayoutOf};
use rustc_target::abi::{Int, Pointer, F32, F64};
use rustc_target::abi::{Primitive, Size, VariantIdx, Variants};
Expand Down Expand Up @@ -751,13 +751,23 @@ pub fn type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>, usage_site_span: Sp
metadata
}

fn hex_encode(data: &[u8]) -> String {
let mut hex_string = String::with_capacity(data.len() * 2);
for byte in data.iter() {
write!(&mut hex_string, "{:02x}", byte).unwrap();
}
hex_string
}

pub fn file_metadata(
cx: &CodegenCx<'ll, '_>,
file_name: &FileName,
defining_crate: CrateNum,
) -> &'ll DIFile {
debug!("file_metadata: file_name: {}, defining_crate: {}", file_name, defining_crate);

let source_file = cx.sess().source_map().get_source_file(file_name);
let hash = source_file.as_ref().map(|f| &f.src_hash);
let file_name = Some(file_name.to_string());
let directory = if defining_crate == LOCAL_CRATE {
Some(cx.sess().working_dir.0.to_string_lossy().to_string())
Expand All @@ -766,17 +776,18 @@ pub fn file_metadata(
// independent of the compiler's working directory one way or another.
None
};
file_metadata_raw(cx, file_name, directory)
file_metadata_raw(cx, file_name, directory, hash)
}

pub fn unknown_file_metadata(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile {
file_metadata_raw(cx, None, None)
file_metadata_raw(cx, None, None, None)
}

fn file_metadata_raw(
cx: &CodegenCx<'ll, '_>,
file_name: Option<String>,
directory: Option<String>,
hash: Option<&SourceFileHash>,
) -> &'ll DIFile {
let key = (file_name, directory);

Expand All @@ -789,13 +800,27 @@ fn file_metadata_raw(
let file_name = file_name.as_deref().unwrap_or("<unknown>");
let directory = directory.as_deref().unwrap_or("");

let (hash_kind, hash_value) = match hash {
Some(hash) => {
let kind = match hash.kind {
rustc_span::SourceFileHashAlgorithm::Md5 => llvm::ChecksumKind::MD5,
rustc_span::SourceFileHashAlgorithm::Sha1 => llvm::ChecksumKind::SHA1,
};
(kind, hex_encode(hash.hash_bytes()))
}
None => (llvm::ChecksumKind::None, String::new()),
};

let file_metadata = unsafe {
llvm::LLVMRustDIBuilderCreateFile(
DIB(cx),
file_name.as_ptr().cast(),
file_name.len(),
directory.as_ptr().cast(),
directory.len(),
hash_kind,
hash_value.as_ptr().cast(),
hash_value.len(),
)
};

Expand Down Expand Up @@ -920,6 +945,9 @@ pub fn compile_unit_metadata(
name_in_debuginfo.len(),
work_dir.as_ptr().cast(),
work_dir.len(),
llvm::ChecksumKind::None,
ptr::null(),
0,
);

let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit(
Expand Down
12 changes: 12 additions & 0 deletions src/librustc_codegen_llvm/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,15 @@ pub enum ThreadLocalMode {
LocalExec,
}

/// LLVMRustChecksumKind
#[derive(Copy, Clone)]
#[repr(C)]
pub enum ChecksumKind {
None,
MD5,
SHA1,
}

extern "C" {
type Opaque;
}
Expand Down Expand Up @@ -1640,6 +1649,9 @@ extern "C" {
FilenameLen: size_t,
Directory: *const c_char,
DirectoryLen: size_t,
CSKind: ChecksumKind,
Checksum: *const c_char,
ChecksumLen: size_t,
) -> &'a DIFile;

pub fn LLVMRustDIBuilderCreateSubroutineType(
Expand Down
8 changes: 3 additions & 5 deletions src/librustc_interface/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use rustc_session::parse::CrateConfig;
use rustc_session::CrateDisambiguator;
use rustc_session::{config, early_error, filesearch, output, DiagnosticOutput, Session};
use rustc_span::edition::Edition;
use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMap};
use rustc_span::source_map::{FileLoader, SourceMap};
use rustc_span::symbol::{sym, Symbol};
use smallvec::SmallVec;
use std::env;
Expand Down Expand Up @@ -62,15 +62,13 @@ pub fn create_session(
lint_caps: FxHashMap<lint::LintId, lint::Level>,
descriptions: Registry,
) -> (Lrc<Session>, Lrc<Box<dyn CodegenBackend>>, Lrc<SourceMap>) {
let loader = file_loader.unwrap_or(box RealFileLoader);
let source_map = Lrc::new(SourceMap::with_file_loader(loader, sopts.file_path_mapping()));
let mut sess = session::build_session_with_source_map(
let (mut sess, source_map) = session::build_session_with_source_map(
sopts,
input_path,
descriptions,
source_map.clone(),
diagnostic_output,
lint_caps,
file_loader,
);

let codegen_backend = get_codegen_backend(&sess);
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_middle/ich/impls_syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
cnum,
// Do not hash the source as it is not encoded
src: _,
src_hash,
ref src_hash,
external_src: _,
start_pos,
end_pos: _,
Expand Down
30 changes: 19 additions & 11 deletions src/librustc_session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ use rustc_feature::UnstableFeatures;
use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST};
use rustc_span::source_map::{FileName, FilePathMapping};
use rustc_span::symbol::{sym, Symbol};
use rustc_span::SourceFileHashAlgorithm;

use rustc_errors::emitter::HumanReadableErrorType;
use rustc_errors::{ColorConfig, FatalError, Handler, HandlerFlags};
use rustc_errors::{ColorConfig, HandlerFlags};

use std::collections::btree_map::{
Iter as BTreeMapIter, Keys as BTreeMapKeysIter, Values as BTreeMapValuesIter,
Expand Down Expand Up @@ -748,25 +749,30 @@ pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateCo
user_cfg
}

pub fn build_target_config(opts: &Options, sp: &Handler) -> Config {
pub fn build_target_config(opts: &Options, error_format: ErrorOutputType) -> Config {
let target = Target::search(&opts.target_triple).unwrap_or_else(|e| {
sp.struct_fatal(&format!("Error loading target specification: {}", e))
.help("Use `--print target-list` for a list of built-in targets")
.emit();
FatalError.raise();
early_error(
error_format,
&format!(
"Error loading target specification: {}. \
Use `--print target-list` for a list of built-in targets",
e
),
)
});

let ptr_width = match &target.target_pointer_width[..] {
"16" => 16,
"32" => 32,
"64" => 64,
w => sp
.fatal(&format!(
w => early_error(
error_format,
&format!(
"target specification was invalid: \
unrecognized target-pointer-width {}",
w
))
.raise(),
),
),
};

Config { target, ptr_width }
Expand Down Expand Up @@ -1971,7 +1977,8 @@ impl PpMode {
crate mod dep_tracking {
use super::{
CFGuard, CrateType, DebugInfo, ErrorOutputType, LinkerPluginLto, LtoCli, OptLevel,
OutputTypes, Passes, Sanitizer, SwitchWithOptPath, SymbolManglingVersion,
OutputTypes, Passes, Sanitizer, SourceFileHashAlgorithm, SwitchWithOptPath,
SymbolManglingVersion,
};
use crate::lint;
use crate::utils::NativeLibraryKind;
Expand Down Expand Up @@ -2049,6 +2056,7 @@ crate mod dep_tracking {
impl_dep_tracking_hash_via_hash!(LinkerPluginLto);
impl_dep_tracking_hash_via_hash!(SwitchWithOptPath);
impl_dep_tracking_hash_via_hash!(SymbolManglingVersion);
impl_dep_tracking_hash_via_hash!(Option<SourceFileHashAlgorithm>);

impl_dep_tracking_hash_for_sortable_vec_of!(String);
impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf);
Expand Down
Loading

0 comments on commit f86b078

Please sign in to comment.