Skip to content

Commit 24e7491

Browse files
committed
Add an abs_path member to FileMap, use it when writing debug info.
When items are inlined from extern crates, the filename in the debug info is taken from the FileMap that's serialized in the rlib metadata. Currently this is just FileMap.name, which is whatever path is passed to rustc. Since libcore and libstd are built by invoking rustc with relative paths, they wind up with relative paths in the rlib, and when linked into a binary the debug info uses relative paths for the names, but since the compilation directory for the final binary, tools trying to read source filenames will wind up with bad paths. We noticed this in Firefox with source filenames from libcore/libstd having bad paths. This change stores an absolute path in FileMap.abs_path, and uses that if available for writing debug info. This is not going to magically make debuggers able to find the source, but it will at least provide sensible paths.
1 parent a479a6a commit 24e7491

File tree

15 files changed

+100
-60
lines changed

15 files changed

+100
-60
lines changed

src/librustc_metadata/creader.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1078,6 +1078,7 @@ pub fn import_codemap(local_codemap: &codemap::CodeMap,
10781078
// containing the information we need.
10791079
let codemap::FileMap {
10801080
name,
1081+
abs_path,
10811082
start_pos,
10821083
end_pos,
10831084
lines,
@@ -1102,6 +1103,7 @@ pub fn import_codemap(local_codemap: &codemap::CodeMap,
11021103
}
11031104

11041105
let local_version = local_codemap.new_imported_filemap(name,
1106+
abs_path,
11051107
source_length,
11061108
lines,
11071109
multibyte_chars);

src/librustc_save_analysis/span_utils.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ impl<'a> SpanUtils<'a> {
8181
// are incompatible with spans over other filemaps.
8282
let filemap = self.sess
8383
.codemap()
84-
.new_filemap(String::from("<anon-dxr>"), self.snippet(span));
84+
.new_filemap(String::from("<anon-dxr>"), None, self.snippet(span));
8585
let s = self.sess;
8686
lexer::StringReader::new(s.diagnostic(), filemap)
8787
}

src/librustc_trans/debuginfo/create_scope_map.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,8 @@ fn make_mir_scope(ccx: &CrateContext,
131131
}
132132

133133
let loc = span_start(ccx, scope_data.span);
134-
let file_metadata = file_metadata(ccx, &loc.file.name);
135134
scopes[scope] = unsafe {
135+
let file_metadata = file_metadata(ccx, &loc.file.name, &loc.file.abs_path);
136136
llvm::LLVMDIBuilderCreateLexicalBlock(
137137
DIB(ccx),
138138
parent_scope,
@@ -152,7 +152,7 @@ fn with_new_scope<F>(cx: &CrateContext,
152152
{
153153
// Create a new lexical scope and push it onto the stack
154154
let loc = span_start(cx, scope_span);
155-
let file_metadata = file_metadata(cx, &loc.file.name);
155+
let file_metadata = file_metadata(cx, &loc.file.name, &loc.file.abs_path);
156156
let parent_scope = scope_stack.last().unwrap().scope_metadata;
157157

158158
let scope_metadata = unsafe {
@@ -268,7 +268,7 @@ fn walk_pattern(cx: &CrateContext,
268268
if need_new_scope {
269269
// Create a new lexical scope and push it onto the stack
270270
let loc = span_start(cx, pat.span);
271-
let file_metadata = file_metadata(cx, &loc.file.name);
271+
let file_metadata = file_metadata(cx, &loc.file.name, &loc.file.abs_path);
272272
let parent_scope = scope_stack.last().unwrap().scope_metadata;
273273

274274
let scope_metadata = unsafe {

src/librustc_trans/debuginfo/metadata.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ fn vec_slice_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
563563
assert!(member_descriptions.len() == member_llvm_types.len());
564564

565565
let loc = span_start(cx, span);
566-
let file_metadata = file_metadata(cx, &loc.file.name);
566+
let file_metadata = file_metadata(cx, &loc.file.name, &loc.file.abs_path);
567567

568568
let metadata = composite_type_metadata(cx,
569569
slice_llvm_type,
@@ -853,17 +853,19 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
853853
metadata
854854
}
855855

856-
pub fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
856+
pub fn file_metadata(cx: &CrateContext, path: &str, full_path: &Option<String>) -> DIFile {
857857
// FIXME (#9639): This needs to handle non-utf8 paths
858858
let work_dir = cx.sess().working_dir.to_str().unwrap();
859859
let file_name =
860-
if full_path.starts_with(work_dir) {
861-
&full_path[work_dir.len() + 1..full_path.len()]
862-
} else {
863-
full_path
864-
};
860+
full_path.as_ref().map(|p| p.as_str()).unwrap_or_else(|| {
861+
if path.starts_with(work_dir) {
862+
&path[work_dir.len() + 1..path.len()]
863+
} else {
864+
path
865+
}
866+
});
865867

866-
file_metadata_(cx, full_path, file_name, &work_dir)
868+
file_metadata_(cx, path, file_name, &work_dir)
867869
}
868870

869871
pub fn unknown_file_metadata(cx: &CrateContext) -> DIFile {
@@ -1849,7 +1851,7 @@ pub fn create_global_var_metadata(cx: &CrateContext,
18491851

18501852
let (file_metadata, line_number) = if span != codemap::DUMMY_SP {
18511853
let loc = span_start(cx, span);
1852-
(file_metadata(cx, &loc.file.name), loc.line as c_uint)
1854+
(file_metadata(cx, &loc.file.name, &loc.file.abs_path), loc.line as c_uint)
18531855
} else {
18541856
(NO_FILE_METADATA, UNKNOWN_LINE_NUMBER)
18551857
};

src/librustc_trans/debuginfo/mod.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
247247
}
248248

249249
let loc = span_start(cx, span);
250-
let file_metadata = file_metadata(cx, &loc.file.name);
250+
let file_metadata = file_metadata(cx, &loc.file.name, &loc.file.abs_path);
251251

252252
let function_type_metadata = unsafe {
253253
let fn_signature = get_function_signature(cx, sig, abi);
@@ -476,8 +476,9 @@ pub fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
476476
span: Span) {
477477
let cx: &CrateContext = bcx.ccx();
478478

479-
let filename = span_start(cx, span).file.name.clone();
480-
let file_metadata = file_metadata(cx, &filename[..]);
479+
let file = span_start(cx, span).file;
480+
let filename = file.name.clone();
481+
let file_metadata = file_metadata(cx, &filename[..], &file.abs_path);
481482

482483
let loc = span_start(cx, span);
483484
let type_metadata = type_metadata(cx, variable_type, span);

src/librustc_trans/debuginfo/namespace.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ pub fn item_namespace(ccx: &CrateContext, def_id: DefId) -> DIScope {
7272
let span = ccx.tcx().map.def_id_span(def_id, DUMMY_SP);
7373
let (file, line) = if span != DUMMY_SP {
7474
let loc = span_start(ccx, span);
75-
(file_metadata(ccx, &loc.file.name), loc.line as c_uint)
75+
(file_metadata(ccx, &loc.file.name, &loc.file.abs_path), loc.line as c_uint)
7676
} else {
7777
(NO_FILE_METADATA, UNKNOWN_LINE_NUMBER)
7878
};

src/librustdoc/html/highlight.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use syntax::parse;
3535
pub fn render_with_highlighting(src: &str, class: Option<&str>, id: Option<&str>) -> String {
3636
debug!("highlighting: ================\n{}\n==============", src);
3737
let sess = parse::ParseSess::new();
38-
let fm = sess.codemap().new_filemap("<stdin>".to_string(), src.to_string());
38+
let fm = sess.codemap().new_filemap("<stdin>".to_string(), None, src.to_string());
3939

4040
let mut out = Vec::new();
4141
write_header(class, id, &mut out).unwrap();
@@ -55,7 +55,7 @@ pub fn render_with_highlighting(src: &str, class: Option<&str>, id: Option<&str>
5555
/// an enclosing `<pre>` block.
5656
pub fn render_inner_with_highlighting(src: &str) -> io::Result<String> {
5757
let sess = parse::ParseSess::new();
58-
let fm = sess.codemap().new_filemap("<stdin>".to_string(), src.to_string());
58+
let fm = sess.codemap().new_filemap("<stdin>".to_string(), None, src.to_string());
5959

6060
let mut out = Vec::new();
6161
let mut classifier = Classifier::new(lexer::StringReader::new(&sess.span_diagnostic, fm),

src/libsyntax/codemap.rs

+51-16
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,11 @@ pub use self::ExpnFormat::*;
2121

2222
use std::cell::{Cell, RefCell};
2323
use std::ops::{Add, Sub};
24-
use std::path::Path;
24+
use std::path::{Path,PathBuf};
2525
use std::rc::Rc;
2626
use std::cmp;
2727

28+
use std::env;
2829
use std::{fmt, fs};
2930
use std::io::{self, Read};
3031

@@ -508,6 +509,8 @@ pub struct FileMap {
508509
/// originate from files has names between angle brackets by convention,
509510
/// e.g. `<anon>`
510511
pub name: FileName,
512+
/// The absolute path of the file that the source came from.
513+
pub abs_path: Option<FileName>,
511514
/// The complete source code
512515
pub src: Option<Rc<String>>,
513516
/// The start position of this source in the CodeMap
@@ -522,11 +525,12 @@ pub struct FileMap {
522525

523526
impl Encodable for FileMap {
524527
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
525-
s.emit_struct("FileMap", 5, |s| {
528+
s.emit_struct("FileMap", 6, |s| {
526529
s.emit_struct_field("name", 0, |s| self.name.encode(s))?;
527-
s.emit_struct_field("start_pos", 1, |s| self.start_pos.encode(s))?;
528-
s.emit_struct_field("end_pos", 2, |s| self.end_pos.encode(s))?;
529-
s.emit_struct_field("lines", 3, |s| {
530+
s.emit_struct_field("abs_path", 1, |s| self.abs_path.encode(s))?;
531+
s.emit_struct_field("start_pos", 2, |s| self.start_pos.encode(s))?;
532+
s.emit_struct_field("end_pos", 3, |s| self.end_pos.encode(s))?;
533+
s.emit_struct_field("lines", 4, |s| {
530534
let lines = self.lines.borrow();
531535
// store the length
532536
s.emit_u32(lines.len() as u32)?;
@@ -572,7 +576,7 @@ impl Encodable for FileMap {
572576

573577
Ok(())
574578
})?;
575-
s.emit_struct_field("multibyte_chars", 4, |s| {
579+
s.emit_struct_field("multibyte_chars", 5, |s| {
576580
(*self.multibyte_chars.borrow()).encode(s)
577581
})
578582
})
@@ -582,11 +586,13 @@ impl Encodable for FileMap {
582586
impl Decodable for FileMap {
583587
fn decode<D: Decoder>(d: &mut D) -> Result<FileMap, D::Error> {
584588

585-
d.read_struct("FileMap", 5, |d| {
589+
d.read_struct("FileMap", 6, |d| {
586590
let name: String = d.read_struct_field("name", 0, |d| Decodable::decode(d))?;
587-
let start_pos: BytePos = d.read_struct_field("start_pos", 1, |d| Decodable::decode(d))?;
588-
let end_pos: BytePos = d.read_struct_field("end_pos", 2, |d| Decodable::decode(d))?;
589-
let lines: Vec<BytePos> = d.read_struct_field("lines", 3, |d| {
591+
let abs_path: Option<String> =
592+
d.read_struct_field("abs_path", 1, |d| Decodable::decode(d))?;
593+
let start_pos: BytePos = d.read_struct_field("start_pos", 2, |d| Decodable::decode(d))?;
594+
let end_pos: BytePos = d.read_struct_field("end_pos", 3, |d| Decodable::decode(d))?;
595+
let lines: Vec<BytePos> = d.read_struct_field("lines", 4, |d| {
590596
let num_lines: u32 = Decodable::decode(d)?;
591597
let mut lines = Vec::with_capacity(num_lines as usize);
592598

@@ -615,9 +621,10 @@ impl Decodable for FileMap {
615621
Ok(lines)
616622
})?;
617623
let multibyte_chars: Vec<MultiByteChar> =
618-
d.read_struct_field("multibyte_chars", 4, |d| Decodable::decode(d))?;
624+
d.read_struct_field("multibyte_chars", 5, |d| Decodable::decode(d))?;
619625
Ok(FileMap {
620626
name: name,
627+
abs_path: abs_path,
621628
start_pos: start_pos,
622629
end_pos: end_pos,
623630
src: None,
@@ -703,6 +710,9 @@ pub trait FileLoader {
703710
/// Query the existence of a file.
704711
fn file_exists(&self, path: &Path) -> bool;
705712

713+
/// Return an absolute path to a file, if possible.
714+
fn abs_path(&self, path: &Path) -> Option<PathBuf>;
715+
706716
/// Read the contents of an UTF-8 file into memory.
707717
fn read_file(&self, path: &Path) -> io::Result<String>;
708718
}
@@ -715,6 +725,16 @@ impl FileLoader for RealFileLoader {
715725
fs::metadata(path).is_ok()
716726
}
717727

728+
fn abs_path(&self, path: &Path) -> Option<PathBuf> {
729+
if path.is_absolute() {
730+
Some(path.to_path_buf())
731+
} else {
732+
env::current_dir()
733+
.ok()
734+
.map(|cwd| cwd.join(path))
735+
}
736+
}
737+
718738
fn read_file(&self, path: &Path) -> io::Result<String> {
719739
let mut src = String::new();
720740
fs::File::open(path)?.read_to_string(&mut src)?;
@@ -755,7 +775,8 @@ impl CodeMap {
755775

756776
pub fn load_file(&self, path: &Path) -> io::Result<Rc<FileMap>> {
757777
let src = self.file_loader.read_file(path)?;
758-
Ok(self.new_filemap(path.to_str().unwrap().to_string(), src))
778+
let abs_path = self.file_loader.abs_path(path).map(|p| p.to_str().unwrap().to_string());
779+
Ok(self.new_filemap(path.to_str().unwrap().to_string(), abs_path, src))
759780
}
760781

761782
fn next_start_pos(&self) -> usize {
@@ -770,7 +791,8 @@ impl CodeMap {
770791

771792
/// Creates a new filemap without setting its line information. If you don't
772793
/// intend to set the line information yourself, you should use new_filemap_and_lines.
773-
pub fn new_filemap(&self, filename: FileName, mut src: String) -> Rc<FileMap> {
794+
pub fn new_filemap(&self, filename: FileName, abs_path: Option<FileName>,
795+
mut src: String) -> Rc<FileMap> {
774796
let start_pos = self.next_start_pos();
775797
let mut files = self.files.borrow_mut();
776798

@@ -783,6 +805,7 @@ impl CodeMap {
783805

784806
let filemap = Rc::new(FileMap {
785807
name: filename,
808+
abs_path: abs_path,
786809
src: Some(Rc::new(src)),
787810
start_pos: Pos::from_usize(start_pos),
788811
end_pos: Pos::from_usize(end_pos),
@@ -796,8 +819,11 @@ impl CodeMap {
796819
}
797820

798821
/// Creates a new filemap and sets its line information.
799-
pub fn new_filemap_and_lines(&self, filename: &str, src: &str) -> Rc<FileMap> {
800-
let fm = self.new_filemap(filename.to_string(), src.to_owned());
822+
pub fn new_filemap_and_lines(&self, filename: &str, abs_path: Option<&str>,
823+
src: &str) -> Rc<FileMap> {
824+
let fm = self.new_filemap(filename.to_string(),
825+
abs_path.map(|s| s.to_owned()),
826+
src.to_owned());
801827
let mut byte_pos: u32 = fm.start_pos.0;
802828
for line in src.lines() {
803829
// register the start of this line
@@ -816,6 +842,7 @@ impl CodeMap {
816842
/// information for things inlined from other crates.
817843
pub fn new_imported_filemap(&self,
818844
filename: FileName,
845+
abs_path: Option<FileName>,
819846
source_len: usize,
820847
mut file_local_lines: Vec<BytePos>,
821848
mut file_local_multibyte_chars: Vec<MultiByteChar>)
@@ -836,6 +863,7 @@ impl CodeMap {
836863

837864
let filemap = Rc::new(FileMap {
838865
name: filename,
866+
abs_path: abs_path,
839867
src: None,
840868
start_pos: start_pos,
841869
end_pos: end_pos,
@@ -1422,6 +1450,7 @@ mod tests {
14221450
fn t1 () {
14231451
let cm = CodeMap::new();
14241452
let fm = cm.new_filemap("blork.rs".to_string(),
1453+
None,
14251454
"first line.\nsecond line".to_string());
14261455
fm.next_line(BytePos(0));
14271456
// Test we can get lines with partial line info.
@@ -1438,6 +1467,7 @@ mod tests {
14381467
fn t2 () {
14391468
let cm = CodeMap::new();
14401469
let fm = cm.new_filemap("blork.rs".to_string(),
1470+
None,
14411471
"first line.\nsecond line".to_string());
14421472
// TESTING *REALLY* BROKEN BEHAVIOR:
14431473
fm.next_line(BytePos(0));
@@ -1448,10 +1478,13 @@ mod tests {
14481478
fn init_code_map() -> CodeMap {
14491479
let cm = CodeMap::new();
14501480
let fm1 = cm.new_filemap("blork.rs".to_string(),
1481+
None,
14511482
"first line.\nsecond line".to_string());
14521483
let fm2 = cm.new_filemap("empty.rs".to_string(),
1484+
None,
14531485
"".to_string());
14541486
let fm3 = cm.new_filemap("blork2.rs".to_string(),
1487+
None,
14551488
"first line.\nsecond line".to_string());
14561489

14571490
fm1.next_line(BytePos(0));
@@ -1514,8 +1547,10 @@ mod tests {
15141547
// € is a three byte utf8 char.
15151548
let fm1 =
15161549
cm.new_filemap("blork.rs".to_string(),
1550+
None,
15171551
"fir€st €€€€ line.\nsecond line".to_string());
15181552
let fm2 = cm.new_filemap("blork2.rs".to_string(),
1553+
None,
15191554
"first line€€.\n€ second line".to_string());
15201555

15211556
fm1.next_line(BytePos(0));
@@ -1583,7 +1618,7 @@ mod tests {
15831618
let cm = CodeMap::new();
15841619
let inputtext = "aaaaa\nbbbbBB\nCCC\nDDDDDddddd\neee\n";
15851620
let selection = " \n ~~\n~~~\n~~~~~ \n \n";
1586-
cm.new_filemap_and_lines("blork.rs", inputtext);
1621+
cm.new_filemap_and_lines("blork.rs", None, inputtext);
15871622
let span = span_from_selection(inputtext, selection);
15881623

15891624
// check that we are extracting the text we thought we were extracting

0 commit comments

Comments
 (0)