Skip to content

Commit

Permalink
Auto merge of #69718 - arlosi:debughash, r=eddyb
Browse files Browse the repository at this point in the history
Add hash of source files in debug info

LLVM supports placing the hash of source files inside the debug info.
This information can be used by a debugger to verify that the source code matches
the executable.

This change adds support for both hash algorithms supported by LLVM, MD5 and SHA1, controlled by a target option.

* DWARF only supports MD5
* LLVM IR supports MD5 and SHA1 (and SHA256 in LLVM 11).
* CodeView (.PDB) supports MD5, SHA1, and SHA256.

Fixes #68980.

Tracking issue: #70401

rustc dev guide PR with further details: rust-lang/rustc-dev-guide#623
  • Loading branch information
bors committed Apr 4, 2020
2 parents 9e55101 + f86b078 commit 6050e52
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 6050e52

Please sign in to comment.