Skip to content

Commit

Permalink
Add an abs_path member to FileMap, use it when writing debug info.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
luser committed Jun 16, 2016
1 parent a479a6a commit 24e7491
Show file tree
Hide file tree
Showing 15 changed files with 100 additions and 60 deletions.
2 changes: 2 additions & 0 deletions src/librustc_metadata/creader.rs
Expand Up @@ -1078,6 +1078,7 @@ pub fn import_codemap(local_codemap: &codemap::CodeMap,
// containing the information we need.
let codemap::FileMap {
name,
abs_path,
start_pos,
end_pos,
lines,
Expand All @@ -1102,6 +1103,7 @@ pub fn import_codemap(local_codemap: &codemap::CodeMap,
}

let local_version = local_codemap.new_imported_filemap(name,
abs_path,
source_length,
lines,
multibyte_chars);
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_save_analysis/span_utils.rs
Expand Up @@ -81,7 +81,7 @@ impl<'a> SpanUtils<'a> {
// are incompatible with spans over other filemaps.
let filemap = self.sess
.codemap()
.new_filemap(String::from("<anon-dxr>"), self.snippet(span));
.new_filemap(String::from("<anon-dxr>"), None, self.snippet(span));
let s = self.sess;
lexer::StringReader::new(s.diagnostic(), filemap)
}
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_trans/debuginfo/create_scope_map.rs
Expand Up @@ -131,8 +131,8 @@ fn make_mir_scope(ccx: &CrateContext,
}

let loc = span_start(ccx, scope_data.span);
let file_metadata = file_metadata(ccx, &loc.file.name);
scopes[scope] = unsafe {
let file_metadata = file_metadata(ccx, &loc.file.name, &loc.file.abs_path);
llvm::LLVMDIBuilderCreateLexicalBlock(
DIB(ccx),
parent_scope,
Expand All @@ -152,7 +152,7 @@ fn with_new_scope<F>(cx: &CrateContext,
{
// Create a new lexical scope and push it onto the stack
let loc = span_start(cx, scope_span);
let file_metadata = file_metadata(cx, &loc.file.name);
let file_metadata = file_metadata(cx, &loc.file.name, &loc.file.abs_path);
let parent_scope = scope_stack.last().unwrap().scope_metadata;

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

let scope_metadata = unsafe {
Expand Down
20 changes: 11 additions & 9 deletions src/librustc_trans/debuginfo/metadata.rs
Expand Up @@ -563,7 +563,7 @@ fn vec_slice_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
assert!(member_descriptions.len() == member_llvm_types.len());

let loc = span_start(cx, span);
let file_metadata = file_metadata(cx, &loc.file.name);
let file_metadata = file_metadata(cx, &loc.file.name, &loc.file.abs_path);

let metadata = composite_type_metadata(cx,
slice_llvm_type,
Expand Down Expand Up @@ -853,17 +853,19 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
metadata
}

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

file_metadata_(cx, full_path, file_name, &work_dir)
file_metadata_(cx, path, file_name, &work_dir)
}

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

let (file_metadata, line_number) = if span != codemap::DUMMY_SP {
let loc = span_start(cx, span);
(file_metadata(cx, &loc.file.name), loc.line as c_uint)
(file_metadata(cx, &loc.file.name, &loc.file.abs_path), loc.line as c_uint)
} else {
(NO_FILE_METADATA, UNKNOWN_LINE_NUMBER)
};
Expand Down
7 changes: 4 additions & 3 deletions src/librustc_trans/debuginfo/mod.rs
Expand Up @@ -247,7 +247,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
}

let loc = span_start(cx, span);
let file_metadata = file_metadata(cx, &loc.file.name);
let file_metadata = file_metadata(cx, &loc.file.name, &loc.file.abs_path);

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

let filename = span_start(cx, span).file.name.clone();
let file_metadata = file_metadata(cx, &filename[..]);
let file = span_start(cx, span).file;
let filename = file.name.clone();
let file_metadata = file_metadata(cx, &filename[..], &file.abs_path);

let loc = span_start(cx, span);
let type_metadata = type_metadata(cx, variable_type, span);
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/debuginfo/namespace.rs
Expand Up @@ -72,7 +72,7 @@ pub fn item_namespace(ccx: &CrateContext, def_id: DefId) -> DIScope {
let span = ccx.tcx().map.def_id_span(def_id, DUMMY_SP);
let (file, line) = if span != DUMMY_SP {
let loc = span_start(ccx, span);
(file_metadata(ccx, &loc.file.name), loc.line as c_uint)
(file_metadata(ccx, &loc.file.name, &loc.file.abs_path), loc.line as c_uint)
} else {
(NO_FILE_METADATA, UNKNOWN_LINE_NUMBER)
};
Expand Down
4 changes: 2 additions & 2 deletions src/librustdoc/html/highlight.rs
Expand Up @@ -35,7 +35,7 @@ use syntax::parse;
pub fn render_with_highlighting(src: &str, class: Option<&str>, id: Option<&str>) -> String {
debug!("highlighting: ================\n{}\n==============", src);
let sess = parse::ParseSess::new();
let fm = sess.codemap().new_filemap("<stdin>".to_string(), src.to_string());
let fm = sess.codemap().new_filemap("<stdin>".to_string(), None, src.to_string());

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

let mut out = Vec::new();
let mut classifier = Classifier::new(lexer::StringReader::new(&sess.span_diagnostic, fm),
Expand Down
67 changes: 51 additions & 16 deletions src/libsyntax/codemap.rs
Expand Up @@ -21,10 +21,11 @@ pub use self::ExpnFormat::*;

use std::cell::{Cell, RefCell};
use std::ops::{Add, Sub};
use std::path::Path;
use std::path::{Path,PathBuf};
use std::rc::Rc;
use std::cmp;

use std::env;
use std::{fmt, fs};
use std::io::{self, Read};

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

impl Encodable for FileMap {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_struct("FileMap", 5, |s| {
s.emit_struct("FileMap", 6, |s| {
s.emit_struct_field("name", 0, |s| self.name.encode(s))?;
s.emit_struct_field("start_pos", 1, |s| self.start_pos.encode(s))?;
s.emit_struct_field("end_pos", 2, |s| self.end_pos.encode(s))?;
s.emit_struct_field("lines", 3, |s| {
s.emit_struct_field("abs_path", 1, |s| self.abs_path.encode(s))?;
s.emit_struct_field("start_pos", 2, |s| self.start_pos.encode(s))?;
s.emit_struct_field("end_pos", 3, |s| self.end_pos.encode(s))?;
s.emit_struct_field("lines", 4, |s| {
let lines = self.lines.borrow();
// store the length
s.emit_u32(lines.len() as u32)?;
Expand Down Expand Up @@ -572,7 +576,7 @@ impl Encodable for FileMap {

Ok(())
})?;
s.emit_struct_field("multibyte_chars", 4, |s| {
s.emit_struct_field("multibyte_chars", 5, |s| {
(*self.multibyte_chars.borrow()).encode(s)
})
})
Expand All @@ -582,11 +586,13 @@ impl Encodable for FileMap {
impl Decodable for FileMap {
fn decode<D: Decoder>(d: &mut D) -> Result<FileMap, D::Error> {

d.read_struct("FileMap", 5, |d| {
d.read_struct("FileMap", 6, |d| {
let name: String = d.read_struct_field("name", 0, |d| Decodable::decode(d))?;
let start_pos: BytePos = d.read_struct_field("start_pos", 1, |d| Decodable::decode(d))?;
let end_pos: BytePos = d.read_struct_field("end_pos", 2, |d| Decodable::decode(d))?;
let lines: Vec<BytePos> = d.read_struct_field("lines", 3, |d| {
let abs_path: Option<String> =
d.read_struct_field("abs_path", 1, |d| Decodable::decode(d))?;
let start_pos: BytePos = d.read_struct_field("start_pos", 2, |d| Decodable::decode(d))?;
let end_pos: BytePos = d.read_struct_field("end_pos", 3, |d| Decodable::decode(d))?;
let lines: Vec<BytePos> = d.read_struct_field("lines", 4, |d| {
let num_lines: u32 = Decodable::decode(d)?;
let mut lines = Vec::with_capacity(num_lines as usize);

Expand Down Expand Up @@ -615,9 +621,10 @@ impl Decodable for FileMap {
Ok(lines)
})?;
let multibyte_chars: Vec<MultiByteChar> =
d.read_struct_field("multibyte_chars", 4, |d| Decodable::decode(d))?;
d.read_struct_field("multibyte_chars", 5, |d| Decodable::decode(d))?;
Ok(FileMap {
name: name,
abs_path: abs_path,
start_pos: start_pos,
end_pos: end_pos,
src: None,
Expand Down Expand Up @@ -703,6 +710,9 @@ pub trait FileLoader {
/// Query the existence of a file.
fn file_exists(&self, path: &Path) -> bool;

/// Return an absolute path to a file, if possible.
fn abs_path(&self, path: &Path) -> Option<PathBuf>;

/// Read the contents of an UTF-8 file into memory.
fn read_file(&self, path: &Path) -> io::Result<String>;
}
Expand All @@ -715,6 +725,16 @@ impl FileLoader for RealFileLoader {
fs::metadata(path).is_ok()
}

fn abs_path(&self, path: &Path) -> Option<PathBuf> {
if path.is_absolute() {
Some(path.to_path_buf())
} else {
env::current_dir()
.ok()
.map(|cwd| cwd.join(path))
}
}

fn read_file(&self, path: &Path) -> io::Result<String> {
let mut src = String::new();
fs::File::open(path)?.read_to_string(&mut src)?;
Expand Down Expand Up @@ -755,7 +775,8 @@ impl CodeMap {

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

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

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

Expand All @@ -783,6 +805,7 @@ impl CodeMap {

let filemap = Rc::new(FileMap {
name: filename,
abs_path: abs_path,
src: Some(Rc::new(src)),
start_pos: Pos::from_usize(start_pos),
end_pos: Pos::from_usize(end_pos),
Expand All @@ -796,8 +819,11 @@ impl CodeMap {
}

/// Creates a new filemap and sets its line information.
pub fn new_filemap_and_lines(&self, filename: &str, src: &str) -> Rc<FileMap> {
let fm = self.new_filemap(filename.to_string(), src.to_owned());
pub fn new_filemap_and_lines(&self, filename: &str, abs_path: Option<&str>,
src: &str) -> Rc<FileMap> {
let fm = self.new_filemap(filename.to_string(),
abs_path.map(|s| s.to_owned()),
src.to_owned());
let mut byte_pos: u32 = fm.start_pos.0;
for line in src.lines() {
// register the start of this line
Expand All @@ -816,6 +842,7 @@ impl CodeMap {
/// information for things inlined from other crates.
pub fn new_imported_filemap(&self,
filename: FileName,
abs_path: Option<FileName>,
source_len: usize,
mut file_local_lines: Vec<BytePos>,
mut file_local_multibyte_chars: Vec<MultiByteChar>)
Expand All @@ -836,6 +863,7 @@ impl CodeMap {

let filemap = Rc::new(FileMap {
name: filename,
abs_path: abs_path,
src: None,
start_pos: start_pos,
end_pos: end_pos,
Expand Down Expand Up @@ -1422,6 +1450,7 @@ mod tests {
fn t1 () {
let cm = CodeMap::new();
let fm = cm.new_filemap("blork.rs".to_string(),
None,
"first line.\nsecond line".to_string());
fm.next_line(BytePos(0));
// Test we can get lines with partial line info.
Expand All @@ -1438,6 +1467,7 @@ mod tests {
fn t2 () {
let cm = CodeMap::new();
let fm = cm.new_filemap("blork.rs".to_string(),
None,
"first line.\nsecond line".to_string());
// TESTING *REALLY* BROKEN BEHAVIOR:
fm.next_line(BytePos(0));
Expand All @@ -1448,10 +1478,13 @@ mod tests {
fn init_code_map() -> CodeMap {
let cm = CodeMap::new();
let fm1 = cm.new_filemap("blork.rs".to_string(),
None,
"first line.\nsecond line".to_string());
let fm2 = cm.new_filemap("empty.rs".to_string(),
None,
"".to_string());
let fm3 = cm.new_filemap("blork2.rs".to_string(),
None,
"first line.\nsecond line".to_string());

fm1.next_line(BytePos(0));
Expand Down Expand Up @@ -1514,8 +1547,10 @@ mod tests {
// € is a three byte utf8 char.
let fm1 =
cm.new_filemap("blork.rs".to_string(),
None,
"fir€st €€€€ line.\nsecond line".to_string());
let fm2 = cm.new_filemap("blork2.rs".to_string(),
None,
"first line€€.\n€ second line".to_string());

fm1.next_line(BytePos(0));
Expand Down Expand Up @@ -1583,7 +1618,7 @@ mod tests {
let cm = CodeMap::new();
let inputtext = "aaaaa\nbbbbBB\nCCC\nDDDDDddddd\neee\n";
let selection = " \n ~~\n~~~\n~~~~~ \n \n";
cm.new_filemap_and_lines("blork.rs", inputtext);
cm.new_filemap_and_lines("blork.rs", None, inputtext);
let span = span_from_selection(inputtext, selection);

// check that we are extracting the text we thought we were extracting
Expand Down

0 comments on commit 24e7491

Please sign in to comment.