Skip to content

Commit 077209e

Browse files
committed
Support file hashes in .debug_line
1 parent a78f851 commit 077209e

File tree

2 files changed

+66
-16
lines changed

2 files changed

+66
-16
lines changed

src/debuginfo/line_info.rs

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
use std::ffi::OsStr;
2+
use std::time::SystemTime;
23
use std::path::{Component, Path};
34

45
use crate::prelude::*;
56

6-
use rustc_span::{FileName, SourceFileAndLine, Pos};
7+
use rustc_span::{FileName, SourceFile, SourceFileAndLine, Pos, SourceFileHash, SourceFileHashAlgorithm};
78

89
use cranelift_codegen::binemit::CodeOffset;
910

1011
use gimli::write::{
11-
Address, AttributeValue, FileId, LineProgram, LineString, LineStringTable, UnitEntryId,
12+
Address, AttributeValue, FileId, LineProgram, LineString, FileInfo, LineStringTable, UnitEntryId,
1213
};
1314

1415
// OPTIMIZATION: It is cheaper to do this in one pass than using `.parent()` and `.file_name()`.
@@ -38,9 +39,9 @@ fn osstr_as_utf8_bytes(path: &OsStr) -> &[u8] {
3839
fn line_program_add_file(
3940
line_program: &mut LineProgram,
4041
line_strings: &mut LineStringTable,
41-
file: &FileName,
42+
file: &SourceFile,
4243
) -> FileId {
43-
match file {
44+
match &file.name {
4445
FileName::Real(path) => {
4546
let (dir_path, file_name) = split_path_dir_and_file(path);
4647
let dir_name = osstr_as_utf8_bytes(dir_path.as_os_str());
@@ -57,13 +58,32 @@ fn line_program_add_file(
5758
line_program.encoding(),
5859
line_strings,
5960
);
60-
line_program.add_file(file_name, dir_id, None)
61+
62+
let md5 = Some(file.src_hash)
63+
.filter(|h| matches!(h, SourceFileHash { kind: SourceFileHashAlgorithm::Md5, .. }))
64+
.map(|h| {
65+
let mut buf = [0u8; super::MD5_LEN];
66+
buf.copy_from_slice(h.hash_bytes());
67+
buf
68+
});
69+
70+
line_program.file_has_timestamp = true;
71+
line_program.file_has_md5 = md5.is_some();
72+
73+
line_program.add_file(file_name, dir_id, Some(FileInfo {
74+
timestamp: SystemTime::now()
75+
.duration_since(SystemTime::UNIX_EPOCH)
76+
.map(|t| t.as_secs())
77+
.unwrap_or(0),
78+
size: 0,
79+
md5: md5.unwrap_or_default(),
80+
}))
6181
}
6282
// FIXME give more appropriate file names
63-
_ => {
83+
filename => {
6484
let dir_id = line_program.default_directory();
6585
let dummy_file_name = LineString::new(
66-
file.to_string().into_bytes(),
86+
filename.to_string().into_bytes(),
6787
line_program.encoding(),
6888
line_strings,
6989
);
@@ -79,7 +99,7 @@ impl<'tcx> DebugContext<'tcx> {
7999
let file_id = line_program_add_file(
80100
&mut self.dwarf.unit.line_program,
81101
&mut self.dwarf.line_strings,
82-
&loc.file.name,
102+
&loc.file,
83103
);
84104

85105
let entry = self.dwarf.unit.get_mut(entry_id);
@@ -167,7 +187,7 @@ impl<'a, 'tcx> FunctionDebugContext<'a, 'tcx> {
167187
true
168188
};
169189
if current_file_changed {
170-
let file_id = line_program_add_file(line_program, line_strings, &file.name);
190+
let file_id = line_program_add_file(line_program, line_strings, &file);
171191
line_program.row().file = file_id;
172192
last_file = Some(file.clone());
173193
}

src/debuginfo/mod.rs

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
mod emit;
22
mod line_info;
33

4+
use std::time::SystemTime;
5+
46
use crate::prelude::*;
57

8+
use rustc_span::{FileName, SourceFileHash, SourceFileHashAlgorithm};
9+
610
use cranelift_codegen::ir::{StackSlots, ValueLabel, ValueLoc};
711
use cranelift_codegen::isa::TargetIsa;
812
use cranelift_codegen::ValueLocRange;
913

1014
use gimli::write::{
1115
self, Address, AttributeValue, DwarfUnit, Expression, LineProgram, LineString, Location,
12-
LocationList, Range, RangeList, UnitEntryId, Writer,
16+
LocationList, Range, RangeList, UnitEntryId, Writer, FileInfo,
1317
};
1418
use gimli::{Encoding, Format, LineEncoding, RunTimeEndian, X86_64};
1519

@@ -24,6 +28,8 @@ fn target_endian(tcx: TyCtxt<'_>) -> RunTimeEndian {
2428
}
2529
}
2630

31+
const MD5_LEN: usize = 16;
32+
2733
pub(crate) struct DebugContext<'tcx> {
2834
tcx: TyCtxt<'tcx>,
2935

@@ -42,7 +48,8 @@ impl<'tcx> DebugContext<'tcx> {
4248
format: Format::Dwarf32,
4349
// TODO: this should be configurable
4450
// macOS doesn't seem to support DWARF > 3
45-
version: 3,
51+
// 5 version is required for md5 file hash
52+
version: 5,
4653
address_size,
4754
};
4855

@@ -52,18 +59,41 @@ impl<'tcx> DebugContext<'tcx> {
5259
// Normally this would use option_env!("CFG_VERSION").
5360
let producer = format!("cg_clif (rustc {})", "unknown version");
5461
let comp_dir = tcx.sess.working_dir.0.to_string_lossy().into_owned();
55-
let name = match tcx.sess.local_crate_source_file {
56-
Some(ref path) => path.to_string_lossy().into_owned(),
57-
None => tcx.crate_name(LOCAL_CRATE).to_string(),
62+
let (name, md5) = match tcx.sess.local_crate_source_file.clone() {
63+
Some(path) => {
64+
let name = path.to_string_lossy().into_owned();
65+
let hash = tcx.sess
66+
.source_map()
67+
.get_source_file(&FileName::Real(path))
68+
.map(|f| f.src_hash)
69+
.filter(|h| matches!(h, SourceFileHash { kind: SourceFileHashAlgorithm::Md5, .. }))
70+
.map(|h| {
71+
let mut buf = [0u8; MD5_LEN];
72+
buf.copy_from_slice(h.hash_bytes());
73+
buf
74+
});
75+
(name, hash)
76+
},
77+
None => (tcx.crate_name(LOCAL_CRATE).to_string(), None),
5878
};
5979

60-
let line_program = LineProgram::new(
80+
let mut line_program = LineProgram::new(
6181
encoding,
6282
LineEncoding::default(),
6383
LineString::new(comp_dir.as_bytes(), encoding, &mut dwarf.line_strings),
6484
LineString::new(name.as_bytes(), encoding, &mut dwarf.line_strings),
65-
None,
85+
Some(FileInfo {
86+
timestamp: SystemTime::now()
87+
.duration_since(SystemTime::UNIX_EPOCH)
88+
.map(|t| t.as_secs())
89+
.unwrap_or(0),
90+
size: 0,
91+
md5: md5.unwrap_or_default(),
92+
}),
6693
);
94+
line_program.file_has_timestamp = true;
95+
line_program.file_has_md5 = md5.is_some();
96+
6797
dwarf.unit.line_program = line_program;
6898

6999
{

0 commit comments

Comments
 (0)