Skip to content

Commit 6050e52

Browse files
committed
Auto merge of rust-lang#69718 - arlosi:debughash, r=eddyb
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 rust-lang#68980. Tracking issue: rust-lang#70401 rustc dev guide PR with further details: rust-lang/rustc-dev-guide#623
2 parents 9e55101 + f86b078 commit 6050e52

File tree

19 files changed

+332
-92
lines changed

19 files changed

+332
-92
lines changed

Cargo.lock

+44-20
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,6 @@ dependencies = [
8787
"scoped_threadpool",
8888
]
8989

90-
[[package]]
91-
name = "arrayref"
92-
version = "0.3.5"
93-
source = "registry+https://github.com/rust-lang/crates.io-index"
94-
checksum = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee"
95-
9690
[[package]]
9791
name = "arrayvec"
9892
version = "0.4.7"
@@ -187,11 +181,22 @@ dependencies = [
187181

188182
[[package]]
189183
name = "block-buffer"
190-
version = "0.3.3"
184+
version = "0.7.3"
185+
source = "registry+https://github.com/rust-lang/crates.io-index"
186+
checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
187+
dependencies = [
188+
"block-padding",
189+
"byte-tools",
190+
"byteorder",
191+
"generic-array",
192+
]
193+
194+
[[package]]
195+
name = "block-padding"
196+
version = "0.1.5"
191197
source = "registry+https://github.com/rust-lang/crates.io-index"
192-
checksum = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab"
198+
checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
193199
dependencies = [
194-
"arrayref",
195200
"byte-tools",
196201
]
197202

@@ -240,9 +245,9 @@ version = "0.1.0"
240245

241246
[[package]]
242247
name = "byte-tools"
243-
version = "0.2.0"
248+
version = "0.3.1"
244249
source = "registry+https://github.com/rust-lang/crates.io-index"
245-
checksum = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"
250+
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
246251

247252
[[package]]
248253
name = "bytecount"
@@ -897,9 +902,9 @@ checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
897902

898903
[[package]]
899904
name = "digest"
900-
version = "0.7.6"
905+
version = "0.8.1"
901906
source = "registry+https://github.com/rust-lang/crates.io-index"
902-
checksum = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"
907+
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
903908
dependencies = [
904909
"generic-array",
905910
]
@@ -1226,9 +1231,9 @@ dependencies = [
12261231

12271232
[[package]]
12281233
name = "generic-array"
1229-
version = "0.9.0"
1234+
version = "0.12.3"
12301235
source = "registry+https://github.com/rust-lang/crates.io-index"
1231-
checksum = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d"
1236+
checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
12321237
dependencies = [
12331238
"typenum",
12341239
]
@@ -1962,6 +1967,17 @@ version = "0.1.8"
19621967
source = "registry+https://github.com/rust-lang/crates.io-index"
19631968
checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
19641969

1970+
[[package]]
1971+
name = "md-5"
1972+
version = "0.8.0"
1973+
source = "registry+https://github.com/rust-lang/crates.io-index"
1974+
checksum = "a18af3dcaf2b0219366cdb4e2af65a6101457b415c3d1a5c71dd9c2b7c77b9c8"
1975+
dependencies = [
1976+
"block-buffer",
1977+
"digest",
1978+
"opaque-debug",
1979+
]
1980+
19651981
[[package]]
19661982
name = "mdbook"
19671983
version = "0.3.5"
@@ -2250,6 +2266,12 @@ version = "1.1.0"
22502266
source = "registry+https://github.com/rust-lang/crates.io-index"
22512267
checksum = "d6a04cb71e910d0034815600180f62a95bf6e67942d7ab52a166a68c7d7e9cd0"
22522268

2269+
[[package]]
2270+
name = "opaque-debug"
2271+
version = "0.2.3"
2272+
source = "registry+https://github.com/rust-lang/crates.io-index"
2273+
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
2274+
22532275
[[package]]
22542276
name = "open"
22552277
version = "1.2.1"
@@ -2467,9 +2489,9 @@ dependencies = [
24672489

24682490
[[package]]
24692491
name = "pest_meta"
2470-
version = "2.1.0"
2492+
version = "2.1.3"
24712493
source = "registry+https://github.com/rust-lang/crates.io-index"
2472-
checksum = "f5a3492a4ed208ffc247adcdcc7ba2a95be3104f58877d0d02f0df39bf3efb5e"
2494+
checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d"
24732495
dependencies = [
24742496
"maplit",
24752497
"pest",
@@ -4155,11 +4177,13 @@ dependencies = [
41554177
"arena",
41564178
"cfg-if",
41574179
"log",
4180+
"md-5",
41584181
"rustc_data_structures",
41594182
"rustc_index",
41604183
"rustc_macros",
41614184
"scoped-tls",
41624185
"serialize",
4186+
"sha-1",
41634187
"unicode-width",
41644188
]
41654189

@@ -4535,14 +4559,14 @@ dependencies = [
45354559

45364560
[[package]]
45374561
name = "sha-1"
4538-
version = "0.7.0"
4562+
version = "0.8.2"
45394563
source = "registry+https://github.com/rust-lang/crates.io-index"
4540-
checksum = "51b9d1f3b5de8a167ab06834a7c883bd197f2191e1dda1a22d9ccfeedbf9aded"
4564+
checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
45414565
dependencies = [
45424566
"block-buffer",
4543-
"byte-tools",
45444567
"digest",
45454568
"fake-simd",
4569+
"opaque-debug",
45464570
]
45474571

45484572
[[package]]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# `src-hash-algorithm`
2+
3+
The tracking issue for this feature is: [#70401](https://github.com/rust-lang/rust/issues/70401).
4+
5+
------------------------
6+
7+
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.
8+
9+
Supported hash algorithms are: `md5`, and `sha1`. Note that not all hash algorithms are supported by all debug info formats.
10+
11+
By default, the compiler chooses the hash algorithm based on the target specification.

src/librustc_codegen_llvm/debuginfo/metadata.rs

+31-3
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ use rustc_middle::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
4141
use rustc_middle::{bug, span_bug};
4242
use rustc_session::config::{self, DebugInfo};
4343
use rustc_span::symbol::{Interner, Symbol};
44-
use rustc_span::{self, FileName, Span};
44+
use rustc_span::{self, FileName, SourceFileHash, Span};
4545
use rustc_target::abi::{Abi, Align, DiscriminantKind, HasDataLayout, Integer, LayoutOf};
4646
use rustc_target::abi::{Int, Pointer, F32, F64};
4747
use rustc_target::abi::{Primitive, Size, VariantIdx, Variants};
@@ -751,13 +751,23 @@ pub fn type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>, usage_site_span: Sp
751751
metadata
752752
}
753753

754+
fn hex_encode(data: &[u8]) -> String {
755+
let mut hex_string = String::with_capacity(data.len() * 2);
756+
for byte in data.iter() {
757+
write!(&mut hex_string, "{:02x}", byte).unwrap();
758+
}
759+
hex_string
760+
}
761+
754762
pub fn file_metadata(
755763
cx: &CodegenCx<'ll, '_>,
756764
file_name: &FileName,
757765
defining_crate: CrateNum,
758766
) -> &'ll DIFile {
759767
debug!("file_metadata: file_name: {}, defining_crate: {}", file_name, defining_crate);
760768

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

772782
pub fn unknown_file_metadata(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile {
773-
file_metadata_raw(cx, None, None)
783+
file_metadata_raw(cx, None, None, None)
774784
}
775785

776786
fn file_metadata_raw(
777787
cx: &CodegenCx<'ll, '_>,
778788
file_name: Option<String>,
779789
directory: Option<String>,
790+
hash: Option<&SourceFileHash>,
780791
) -> &'ll DIFile {
781792
let key = (file_name, directory);
782793

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

803+
let (hash_kind, hash_value) = match hash {
804+
Some(hash) => {
805+
let kind = match hash.kind {
806+
rustc_span::SourceFileHashAlgorithm::Md5 => llvm::ChecksumKind::MD5,
807+
rustc_span::SourceFileHashAlgorithm::Sha1 => llvm::ChecksumKind::SHA1,
808+
};
809+
(kind, hex_encode(hash.hash_bytes()))
810+
}
811+
None => (llvm::ChecksumKind::None, String::new()),
812+
};
813+
792814
let file_metadata = unsafe {
793815
llvm::LLVMRustDIBuilderCreateFile(
794816
DIB(cx),
795817
file_name.as_ptr().cast(),
796818
file_name.len(),
797819
directory.as_ptr().cast(),
798820
directory.len(),
821+
hash_kind,
822+
hash_value.as_ptr().cast(),
823+
hash_value.len(),
799824
)
800825
};
801826

@@ -920,6 +945,9 @@ pub fn compile_unit_metadata(
920945
name_in_debuginfo.len(),
921946
work_dir.as_ptr().cast(),
922947
work_dir.len(),
948+
llvm::ChecksumKind::None,
949+
ptr::null(),
950+
0,
923951
);
924952

925953
let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit(

src/librustc_codegen_llvm/llvm/ffi.rs

+12
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,15 @@ pub enum ThreadLocalMode {
546546
LocalExec,
547547
}
548548

549+
/// LLVMRustChecksumKind
550+
#[derive(Copy, Clone)]
551+
#[repr(C)]
552+
pub enum ChecksumKind {
553+
None,
554+
MD5,
555+
SHA1,
556+
}
557+
549558
extern "C" {
550559
type Opaque;
551560
}
@@ -1640,6 +1649,9 @@ extern "C" {
16401649
FilenameLen: size_t,
16411650
Directory: *const c_char,
16421651
DirectoryLen: size_t,
1652+
CSKind: ChecksumKind,
1653+
Checksum: *const c_char,
1654+
ChecksumLen: size_t,
16431655
) -> &'a DIFile;
16441656

16451657
pub fn LLVMRustDIBuilderCreateSubroutineType(

src/librustc_interface/util.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use rustc_session::parse::CrateConfig;
2222
use rustc_session::CrateDisambiguator;
2323
use rustc_session::{config, early_error, filesearch, output, DiagnosticOutput, Session};
2424
use rustc_span::edition::Edition;
25-
use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMap};
25+
use rustc_span::source_map::{FileLoader, SourceMap};
2626
use rustc_span::symbol::{sym, Symbol};
2727
use smallvec::SmallVec;
2828
use std::env;
@@ -62,15 +62,13 @@ pub fn create_session(
6262
lint_caps: FxHashMap<lint::LintId, lint::Level>,
6363
descriptions: Registry,
6464
) -> (Lrc<Session>, Lrc<Box<dyn CodegenBackend>>, Lrc<SourceMap>) {
65-
let loader = file_loader.unwrap_or(box RealFileLoader);
66-
let source_map = Lrc::new(SourceMap::with_file_loader(loader, sopts.file_path_mapping()));
67-
let mut sess = session::build_session_with_source_map(
65+
let (mut sess, source_map) = session::build_session_with_source_map(
6866
sopts,
6967
input_path,
7068
descriptions,
71-
source_map.clone(),
7269
diagnostic_output,
7370
lint_caps,
71+
file_loader,
7472
);
7573

7674
let codegen_backend = get_codegen_backend(&sess);

src/librustc_middle/ich/impls_syntax.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
6161
cnum,
6262
// Do not hash the source as it is not encoded
6363
src: _,
64-
src_hash,
64+
ref src_hash,
6565
external_src: _,
6666
start_pos,
6767
end_pos: _,

src/librustc_session/config.rs

+19-11
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ use rustc_feature::UnstableFeatures;
1818
use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST};
1919
use rustc_span::source_map::{FileName, FilePathMapping};
2020
use rustc_span::symbol::{sym, Symbol};
21+
use rustc_span::SourceFileHashAlgorithm;
2122

2223
use rustc_errors::emitter::HumanReadableErrorType;
23-
use rustc_errors::{ColorConfig, FatalError, Handler, HandlerFlags};
24+
use rustc_errors::{ColorConfig, HandlerFlags};
2425

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

751-
pub fn build_target_config(opts: &Options, sp: &Handler) -> Config {
752+
pub fn build_target_config(opts: &Options, error_format: ErrorOutputType) -> Config {
752753
let target = Target::search(&opts.target_triple).unwrap_or_else(|e| {
753-
sp.struct_fatal(&format!("Error loading target specification: {}", e))
754-
.help("Use `--print target-list` for a list of built-in targets")
755-
.emit();
756-
FatalError.raise();
754+
early_error(
755+
error_format,
756+
&format!(
757+
"Error loading target specification: {}. \
758+
Use `--print target-list` for a list of built-in targets",
759+
e
760+
),
761+
)
757762
});
758763

759764
let ptr_width = match &target.target_pointer_width[..] {
760765
"16" => 16,
761766
"32" => 32,
762767
"64" => 64,
763-
w => sp
764-
.fatal(&format!(
768+
w => early_error(
769+
error_format,
770+
&format!(
765771
"target specification was invalid: \
766772
unrecognized target-pointer-width {}",
767773
w
768-
))
769-
.raise(),
774+
),
775+
),
770776
};
771777

772778
Config { target, ptr_width }
@@ -1971,7 +1977,8 @@ impl PpMode {
19711977
crate mod dep_tracking {
19721978
use super::{
19731979
CFGuard, CrateType, DebugInfo, ErrorOutputType, LinkerPluginLto, LtoCli, OptLevel,
1974-
OutputTypes, Passes, Sanitizer, SwitchWithOptPath, SymbolManglingVersion,
1980+
OutputTypes, Passes, Sanitizer, SourceFileHashAlgorithm, SwitchWithOptPath,
1981+
SymbolManglingVersion,
19751982
};
19761983
use crate::lint;
19771984
use crate::utils::NativeLibraryKind;
@@ -2049,6 +2056,7 @@ crate mod dep_tracking {
20492056
impl_dep_tracking_hash_via_hash!(LinkerPluginLto);
20502057
impl_dep_tracking_hash_via_hash!(SwitchWithOptPath);
20512058
impl_dep_tracking_hash_via_hash!(SymbolManglingVersion);
2059+
impl_dep_tracking_hash_via_hash!(Option<SourceFileHashAlgorithm>);
20522060

20532061
impl_dep_tracking_hash_for_sortable_vec_of!(String);
20542062
impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf);

0 commit comments

Comments
 (0)