Skip to content

debuginfo: Fix issue with DWARF compile unit names #11846

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 28, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 24 additions & 20 deletions src/librustc/driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -897,42 +897,56 @@ pub fn build_session_options(binary: ~str,
return sopts;
}

pub fn build_session(sopts: @session::Options, demitter: @diagnostic::Emitter)
pub fn build_session(sopts: @session::Options,
local_crate_source_file: Option<Path>,
demitter: @diagnostic::Emitter)
-> Session {
let codemap = @codemap::CodeMap::new();
let diagnostic_handler =
diagnostic::mk_handler(Some(demitter));
let span_diagnostic_handler =
diagnostic::mk_span_handler(diagnostic_handler, codemap);
build_session_(sopts, codemap, demitter, span_diagnostic_handler)

build_session_(sopts, local_crate_source_file, codemap, demitter, span_diagnostic_handler)
}

pub fn build_session_(sopts: @session::Options,
cm: @codemap::CodeMap,
local_crate_source_file: Option<Path>,
codemap: @codemap::CodeMap,
demitter: @diagnostic::Emitter,
span_diagnostic_handler: @diagnostic::SpanHandler)
-> Session {
let target_cfg = build_target_config(sopts, demitter);
let p_s = parse::new_parse_sess_special_handler(span_diagnostic_handler,
cm);
let p_s = parse::new_parse_sess_special_handler(span_diagnostic_handler, codemap);
let cstore = @CStore::new(token::get_ident_interner());
let filesearch = @filesearch::FileSearch::new(
&sopts.maybe_sysroot,
sopts.target_triple,
sopts.addl_lib_search_paths);

// Make the path absolute, if necessary
let local_crate_source_file = local_crate_source_file.map(|path|
if path.is_absolute() {
path.clone()
} else {
os::getcwd().join(path.clone())
}
);

@Session_ {
targ_cfg: target_cfg,
opts: sopts,
cstore: cstore,
parse_sess: p_s,
codemap: cm,
codemap: codemap,
// For a library crate, this is always none
entry_fn: RefCell::new(None),
entry_type: Cell::new(None),
macro_registrar_fn: RefCell::new(None),
span_diagnostic: span_diagnostic_handler,
filesearch: filesearch,
building_library: Cell::new(false),
local_crate_source_file: local_crate_source_file,
working_dir: os::getcwd(),
lints: RefCell::new(HashMap::new()),
node_id: Cell::new(1),
Expand Down Expand Up @@ -1164,13 +1178,8 @@ mod test {
Ok(m) => m,
Err(f) => fail!("test_switch_implies_cfg_test: {}", f.to_err_msg())
};
let sessopts = build_session_options(
~"rustc",
matches,
@diagnostic::DefaultEmitter as @diagnostic::Emitter);
let sess = build_session(sessopts,
@diagnostic::DefaultEmitter as
@diagnostic::Emitter);
let sessopts = build_session_options(~"rustc", matches, @diagnostic::DefaultEmitter);
let sess = build_session(sessopts, None, @diagnostic::DefaultEmitter);
let cfg = build_configuration(sess);
assert!((attr::contains_name(cfg, "test")));
}
Expand All @@ -1187,13 +1196,8 @@ mod test {
f.to_err_msg());
}
};
let sessopts = build_session_options(
~"rustc",
matches,
@diagnostic::DefaultEmitter as @diagnostic::Emitter);
let sess = build_session(sessopts,
@diagnostic::DefaultEmitter as
@diagnostic::Emitter);
let sessopts = build_session_options(~"rustc", matches, @diagnostic::DefaultEmitter);
let sess = build_session(sessopts, None, @diagnostic::DefaultEmitter);
let cfg = build_configuration(sess);
let mut test_items = cfg.iter().filter(|m| "test" == m.name());
assert!(test_items.next().is_some());
Expand Down
3 changes: 3 additions & 0 deletions src/librustc/driver/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,9 @@ pub struct Session_ {
macro_registrar_fn: RefCell<Option<ast::DefId>>,
filesearch: @filesearch::FileSearch,
building_library: Cell<bool>,
// The name of the root source file of the crate, in the local file system. The path is always
// expected to be absolute. `None` means that there is no source file.
local_crate_source_file: Option<Path>,
working_dir: Path,
lints: RefCell<HashMap<ast::NodeId,
~[(lint::Lint, codemap::Span, ~str)]>>,
Expand Down
8 changes: 4 additions & 4 deletions src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,22 +230,22 @@ pub fn run_compiler(args: &[~str], demitter: @diagnostic::Emitter) {
version(binary);
return;
}
let input = match matches.free.len() {
let (input, input_file_path) = match matches.free.len() {
0u => d::early_error(demitter, "no input filename given"),
1u => {
let ifile = matches.free[0].as_slice();
if "-" == ifile {
let src = str::from_utf8_owned(io::stdin().read_to_end()).unwrap();
d::StrInput(src.to_managed())
(d::StrInput(src.to_managed()), None)
} else {
d::FileInput(Path::new(ifile))
(d::FileInput(Path::new(ifile)), Some(Path::new(ifile)))
}
}
_ => d::early_error(demitter, "multiple input filenames provided")
};

let sopts = d::build_session_options(binary, matches, demitter);
let sess = d::build_session(sopts, demitter);
let sess = d::build_session(sopts, input_file_path, demitter);
let odir = matches.opt_str("out-dir").map(|o| Path::new(o));
let ofile = matches.opt_str("o").map(|o| Path::new(o));
let cfg = d::build_configuration(sess);
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2741,15 +2741,15 @@ pub fn trans_crate(sess: session::Session,
let link_meta = link::build_link_meta(sess, crate.attrs, output,
&mut symbol_hasher);

// Append ".rc" to crate name as LLVM module identifier.
// Append ".rs" to crate name as LLVM module identifier.
//
// LLVM code generator emits a ".file filename" directive
// for ELF backends. Value of the "filename" is set as the
// LLVM module identifier. Due to a LLVM MC bug[1], LLVM
// crashes if the module identifer is same as other symbols
// such as a function name in the module.
// 1. http://llvm.org/bugs/show_bug.cgi?id=11479
let llmod_id = link_meta.crateid.name.clone() + ".rc";
let llmod_id = link_meta.crateid.name.clone() + ".rs";

let ccx = @CrateContext::new(sess,
llmod_id,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ impl CrateContext {

let (crate_map_name, crate_map) = decl_crate_map(sess, link_meta.clone(), llmod);
let dbg_cx = if sess.opts.debuginfo {
Some(debuginfo::CrateDebugContext::new(llmod, name.to_owned()))
Some(debuginfo::CrateDebugContext::new(llmod))
} else {
None
};
Expand Down
55 changes: 40 additions & 15 deletions src/librustc/middle/trans/debuginfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ use middle::ty;
use middle::pat_util;
use util::ppaux;

use std::c_str::ToCStr;
use std::c_str::{CString, ToCStr};
use std::cell::{Cell, RefCell};
use std::hashmap::HashMap;
use std::hashmap::HashSet;
Expand Down Expand Up @@ -173,7 +173,6 @@ static DW_ATE_unsigned_char: c_uint = 0x08;

/// A context object for maintaining all state needed by the debuginfo module.
pub struct CrateDebugContext {
priv crate_file: ~str,
priv llcontext: ContextRef,
priv builder: DIBuilderRef,
priv current_debug_location: Cell<DebugLocation>,
Expand All @@ -186,13 +185,12 @@ pub struct CrateDebugContext {
}

impl CrateDebugContext {
pub fn new(llmod: ModuleRef, crate: ~str) -> CrateDebugContext {
pub fn new(llmod: ModuleRef) -> CrateDebugContext {
debug!("CrateDebugContext::new");
let builder = unsafe { llvm::LLVMDIBuilderCreate(llmod) };
// DIBuilder inherits context from the module, so we'd better use the same one
let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
return CrateDebugContext {
crate_file: crate,
llcontext: llcontext,
builder: builder,
current_debug_location: Cell::new(UnknownLocation),
Expand Down Expand Up @@ -929,26 +927,49 @@ fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
};
}

fn compile_unit_metadata(cx: @CrateContext) {
let dcx = debug_context(cx);
let crate_name: &str = dcx.crate_file;

debug!("compile_unit_metadata: {:?}", crate_name);
fn compile_unit_metadata(cx: &CrateContext) {
let work_dir = &cx.sess.working_dir;
let compile_unit_name = match cx.sess.local_crate_source_file {
None => fallback_path(cx),
Some(ref abs_path) => {
if abs_path.is_relative() {
cx.sess.warn("debuginfo: Invalid path to crate's local root source file!");
fallback_path(cx)
} else {
match abs_path.path_relative_from(work_dir) {
Some(ref p) if p.is_relative() => {
// prepend "./" if necessary
let dotdot = bytes!("..");
let prefix = &[dotdot[0], ::std::path::SEP_BYTE];
let mut path_bytes = p.as_vec().to_owned();

if path_bytes.slice_to(2) != prefix &&
path_bytes.slice_to(2) != dotdot {
path_bytes.insert(0, prefix[0]);
path_bytes.insert(1, prefix[1]);
}

path_bytes.to_c_str()
}
_ => fallback_path(cx)
}
}
}
};

// FIXME (#9639): This needs to handle non-utf8 paths
let work_dir = cx.sess.working_dir.as_str().unwrap();
debug!("compile_unit_metadata: {:?}", compile_unit_name);
let producer = format!("rustc version {}", env!("CFG_VERSION"));

crate_name.with_c_str(|crate_name| {
work_dir.with_c_str(|work_dir| {
compile_unit_name.with_ref(|compile_unit_name| {
work_dir.as_vec().with_c_str(|work_dir| {
producer.with_c_str(|producer| {
"".with_c_str(|flags| {
"".with_c_str(|split_name| {
unsafe {
llvm::LLVMDIBuilderCreateCompileUnit(
dcx.builder,
debug_context(cx).builder,
DW_LANG_RUST,
crate_name,
compile_unit_name,
work_dir,
producer,
cx.sess.opts.optimize != session::No,
Expand All @@ -961,6 +982,10 @@ fn compile_unit_metadata(cx: @CrateContext) {
})
})
});

fn fallback_path(cx: &CrateContext) -> CString {
cx.link_meta.crateid.name.to_c_str()
}
}

fn declare_local(bcx: &Block,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/typeck/infer/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ fn setup_env(test_name: &str, source_string: &str) -> Env {
let matches = getopts(~[~"-Z", ~"verbose"], optgroups()).get();
let diag = diagnostic::collect(messages);
let sessopts = build_session_options(~"rustc", &matches, diag);
let sess = build_session(sessopts, diag);
let sess = build_session(sessopts, None, diag);
let cfg = build_configuration(sess, ~"whatever", str_input(~""));
let dm = HashMap();
let amap = HashMap();
Expand Down
4 changes: 2 additions & 2 deletions src/librustdoc/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ fn get_ast_and_resolve(cpath: &Path,
syntax::diagnostic::mk_span_handler(diagnostic_handler, parsesess.cm);

let sess = driver::driver::build_session_(sessopts,
Some(cpath.clone()),
parsesess.cm,
@diagnostic::DefaultEmitter as
@diagnostic::Emitter,
@diagnostic::DefaultEmitter,
span_diagnostic_handler);

let mut cfg = build_configuration(sess);
Expand Down
11 changes: 6 additions & 5 deletions src/librustdoc/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ use visit_ast::RustdocVisitor;

pub fn run(input: &str, matches: &getopts::Matches) -> int {
let parsesess = parse::new_parse_sess(None);
let input = driver::FileInput(Path::new(input));
let input_path = Path::new(input);
let input = driver::FileInput(input_path.clone());
let libs = matches.opt_strs("L").map(|s| Path::new(s.as_slice()));
let libs = @RefCell::new(libs.move_iter().collect());

Expand All @@ -52,9 +53,9 @@ pub fn run(input: &str, matches: &getopts::Matches) -> int {
diagnostic::mk_span_handler(diagnostic_handler, parsesess.cm);

let sess = driver::build_session_(sessopts,
Some(input_path),
parsesess.cm,
@diagnostic::DefaultEmitter as
@diagnostic::Emitter,
@diagnostic::DefaultEmitter,
span_diagnostic_handler);

let cfg = driver::build_configuration(sess);
Expand Down Expand Up @@ -113,9 +114,9 @@ fn runtest(test: &str, cratename: &str, libs: HashSet<Path>) {
diagnostic::mk_span_handler(diagnostic_handler, parsesess.cm);

let sess = driver::build_session_(sessopts,
None,
parsesess.cm,
@diagnostic::DefaultEmitter as
@diagnostic::Emitter,
@diagnostic::DefaultEmitter,
span_diagnostic_handler);

let outdir = TempDir::new("rustdoctest").expect("rustdoc needs a tempdir");
Expand Down
4 changes: 2 additions & 2 deletions src/librustpkg/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ impl<'a> PkgScript<'a> {
};
let input = driver::FileInput(script.clone());
let sess = driver::build_session(options,
@diagnostic::DefaultEmitter as
@diagnostic::Emitter);
Some(script.clone()),
@diagnostic::DefaultEmitter);
let cfg = driver::build_configuration(sess);
let crate = driver::phase_1_parse_input(sess, cfg.clone(), &input);
let loader = &mut Loader::new(sess);
Expand Down
7 changes: 2 additions & 5 deletions src/librustpkg/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1770,11 +1770,8 @@ fn test_linker_build() {
let matches = getopts([], optgroups());
let options = build_session_options(~"rustpkg",
matches.as_ref().unwrap(),
@diagnostic::DefaultEmitter as
@diagnostic::Emitter);
let sess = build_session(options,
@diagnostic::DefaultEmitter as
@diagnostic::Emitter);
@diagnostic::DefaultEmitter);
let sess = build_session(options, None, @diagnostic::DefaultEmitter);
let test_sys = test_sysroot();
// FIXME (#9639): This needs to handle non-utf8 paths
let cc = get_cc_prog(sess);
Expand Down
1 change: 1 addition & 0 deletions src/librustpkg/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ pub fn compile_input(context: &BuildContext,
debug!("About to build session...");

let sess = driver::build_session(options,
Some(in_file.clone()),
@diagnostic::DefaultEmitter as
@diagnostic::Emitter);

Expand Down
27 changes: 27 additions & 0 deletions src/test/debug-info/issue11600.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
fn main() {
let args : ~[~str] = ::std::os::args();
::std::io::println(args[0]);
}


// xfail-android: FIXME(#10381)

// This test case checks whether compile unit names are set correctly, so that the correct default
// source file can be found.

// compile-flags:-Z extra-debug-info
// debugger:list
// check:1[...]fn main() {
// check:2[...]let args : ~[~str] = ::std::os::args();
// check:3[...]::std::io::println(args[0]);
// check:4[...]}

// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.