From 32a2e9a8e15ee93dbd663fa3849604979df1142f Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 12 Feb 2016 08:41:30 -0500 Subject: [PATCH] Compute a salt from arguments passed via -Cmetadata. --- src/librbml/lib.rs | 4 ++-- src/librustc/middle/cstore.rs | 2 ++ src/librustc/session/mod.rs | 9 +++++++-- src/librustc_back/svh.rs | 8 ++++---- src/librustc_driver/driver.rs | 33 +++++++++++++++++++++++++++++--- src/librustc_driver/lib.rs | 2 -- src/librustc_metadata/common.rs | 1 + src/librustc_metadata/csearch.rs | 6 ++++++ src/librustc_metadata/decoder.rs | 7 +++++++ src/librustc_metadata/encoder.rs | 5 +++++ src/librustc_trans/back/link.rs | 8 +++----- 11 files changed, 67 insertions(+), 18 deletions(-) diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs index 34726a7a6c8..ef89b5d25b8 100644 --- a/src/librbml/lib.rs +++ b/src/librbml/lib.rs @@ -166,7 +166,7 @@ pub fn new(data: &'doc [u8]) -> Doc<'doc> { } } - pub fn get<'a>(&'a self, tag: usize) -> Doc<'a> { + pub fn get(&self, tag: usize) -> Doc<'doc> { reader::get_doc(*self, tag) } @@ -174,7 +174,7 @@ pub fn is_empty(&self) -> bool { self.start == self.end } - pub fn as_str_slice<'a>(&'a self) -> &'a str { + pub fn as_str_slice(&self) -> &'doc str { str::from_utf8(&self.data[self.start..self.end]).unwrap() } diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index b89fd92e3c5..718a9fd58de 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -206,6 +206,7 @@ fn dylib_dependency_formats(&self, cnum: ast::CrateNum) fn crate_attrs(&self, cnum: ast::CrateNum) -> Vec; fn crate_name(&self, cnum: ast::CrateNum) -> InternedString; fn crate_hash(&self, cnum: ast::CrateNum) -> Svh; + fn crate_disambiguator(&self, cnum: ast::CrateNum) -> InternedString; fn crate_struct_field_attrs(&self, cnum: ast::CrateNum) -> FnvHashMap>; fn plugin_registrar_fn(&self, cnum: ast::CrateNum) -> Option; @@ -385,6 +386,7 @@ fn crate_attrs(&self, cnum: ast::CrateNum) -> Vec { unimplemented!() } fn crate_name(&self, cnum: ast::CrateNum) -> InternedString { unimplemented!() } fn crate_hash(&self, cnum: ast::CrateNum) -> Svh { unimplemented!() } + fn crate_disambiguator(&self, cnum: ast::CrateNum) -> InternedString { unimplemented!() } fn crate_struct_field_attrs(&self, cnum: ast::CrateNum) -> FnvHashMap> { unimplemented!() } diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index b198eda1812..36dc8eabc89 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -64,7 +64,12 @@ pub struct Session { pub plugin_attributes: RefCell>, pub crate_types: RefCell>, pub dependency_formats: RefCell, - pub crate_metadata: RefCell>, + // The crate_disambiguator is constructed out of all the `-C metadata` + // arguments passed to the compiler. Its value together with the crate-name + // forms a unique global identifier for the crate. It is used to allow + // multiple crates with the same name to coexist. See the + // trans::back::symbol_names module for more information. + pub crate_disambiguator: RefCell, pub features: RefCell, /// The maximum recursion limit for potentially infinitely recursive @@ -481,7 +486,7 @@ pub fn build_session_(sopts: config::Options, plugin_attributes: RefCell::new(Vec::new()), crate_types: RefCell::new(Vec::new()), dependency_formats: RefCell::new(FnvHashMap()), - crate_metadata: RefCell::new(Vec::new()), + crate_disambiguator: RefCell::new(String::new()), features: RefCell::new(feature_gate::Features::new()), recursion_limit: Cell::new(64), next_node_id: Cell::new(1), diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs index 3507a119e54..ec607314f45 100644 --- a/src/librustc_back/svh.rs +++ b/src/librustc_back/svh.rs @@ -66,7 +66,7 @@ pub fn as_str<'a>(&'a self) -> &'a str { &self.hash } - pub fn calculate(metadata: &Vec, krate: &hir::Crate) -> Svh { + pub fn calculate(crate_disambiguator: &str, krate: &hir::Crate) -> Svh { // FIXME (#14132): This is better than it used to be, but it still not // ideal. We now attempt to hash only the relevant portions of the // Crate AST as well as the top-level crate attributes. (However, @@ -78,9 +78,9 @@ pub fn calculate(metadata: &Vec, krate: &hir::Crate) -> Svh { // avoid collisions. let mut state = SipHasher::new(); - for data in metadata { - data.hash(&mut state); - } + "crate_disambiguator".hash(&mut state); + crate_disambiguator.len().hash(&mut state); + crate_disambiguator.hash(&mut state); { let mut visit = svh_visitor::make(&mut state, krate); diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 55b873c0663..b75ccb3f7ee 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -22,6 +22,7 @@ use rustc::middle::ty::TyCtxt; use rustc::util::common::time; use rustc::util::nodemap::NodeSet; +use rustc_back::sha2::{Sha256, Digest}; use rustc_borrowck as borrowck; use rustc_resolve as resolve; use rustc_metadata::macro_import; @@ -500,7 +501,7 @@ pub fn phase_2_configure_and_expand(sess: &Session, })?; *sess.crate_types.borrow_mut() = collect_crate_types(sess, &krate.attrs); - *sess.crate_metadata.borrow_mut() = collect_crate_metadata(sess, &krate.attrs); + *sess.crate_disambiguator.borrow_mut() = compute_crate_disambiguator(sess); time(time_passes, "recursion limit", || { middle::recursion_limit::update_recursion_limit(sess, &krate); @@ -1121,8 +1122,34 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec Vec { - session.opts.cg.metadata.clone() +pub fn compute_crate_disambiguator(session: &Session) -> String { + let mut hasher = Sha256::new(); + + let mut metadata = session.opts.cg.metadata.clone(); + // We don't want the crate_disambiguator to dependent on the order + // -C metadata arguments, so sort them: + metadata.sort(); + // Every distinct -C metadata value is only incorporated once: + metadata.dedup(); + + hasher.input_str("metadata"); + for s in &metadata { + // Also incorporate the length of a metadata string, so that we generate + // different values for `-Cmetadata=ab -Cmetadata=c` and + // `-Cmetadata=a -Cmetadata=bc` + hasher.input_str(&format!("{}", s.len())[..]); + hasher.input_str(&s[..]); + } + + let mut hash = hasher.result_str(); + + // If this is an executable, add a special suffix, so that we don't get + // symbol conflicts when linking against a library of the same name. + if session.crate_types.borrow().contains(&config::CrateTypeExecutable) { + hash.push_str("-exe"); + } + + hash } pub fn build_output_filenames(input: &Input, diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index dc30b4f91a9..9ba6abb962e 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -568,8 +568,6 @@ fn print_crate_info(sess: &Session, continue; } let crate_types = driver::collect_crate_types(sess, attrs); - let metadata = driver::collect_crate_metadata(sess, attrs); - *sess.crate_metadata.borrow_mut() = metadata; for &style in &crate_types { let fname = link::filename_for_input(sess, style, &id, &t_outputs); println!("{}", diff --git a/src/librustc_metadata/common.rs b/src/librustc_metadata/common.rs index a0cbba279ac..22a5289f02b 100644 --- a/src/librustc_metadata/common.rs +++ b/src/librustc_metadata/common.rs @@ -73,6 +73,7 @@ pub const tag_crate_hash: usize = 0x103; // top-level only pub const tag_crate_crate_name: usize = 0x104; // top-level only +pub const tag_crate_disambiguator: usize = 0x113; // top-level only pub const tag_crate_dep_crate_name: usize = 0x36; pub const tag_crate_dep_hash: usize = 0x37; diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index 9514317056a..f9446d7667c 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -345,6 +345,12 @@ fn crate_hash(&self, cnum: ast::CrateNum) -> Svh decoder::get_crate_hash(cdata.data()) } + fn crate_disambiguator(&self, cnum: ast::CrateNum) -> token::InternedString + { + let cdata = self.get_crate_data(cnum); + token::intern_and_get_ident(decoder::get_crate_disambiguator(cdata.data())) + } + fn crate_struct_field_attrs(&self, cnum: ast::CrateNum) -> FnvHashMap> { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 0c736feeefe..f24c489b7c2 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1295,6 +1295,13 @@ pub fn maybe_get_crate_name(data: &[u8]) -> Option { }) } +pub fn get_crate_disambiguator<'a>(data: &'a [u8]) -> &'a str { + let crate_doc = rbml::Doc::new(data); + let salt_doc = reader::get_doc(crate_doc, tag_crate_disambiguator); + let slice: &'a str = salt_doc.as_str_slice(); + slice +} + pub fn get_crate_triple(data: &[u8]) -> Option { let cratedoc = rbml::Doc::new(data); let triple_doc = reader::maybe_get_doc(cratedoc, tag_crate_triple); diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index a082b0f21f1..a58c24eb09f 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1877,6 +1877,10 @@ fn encode_crate_name(rbml_w: &mut Encoder, crate_name: &str) { rbml_w.wr_tagged_str(tag_crate_crate_name, crate_name); } +fn encode_crate_disambiguator(rbml_w: &mut Encoder, crate_disambiguator: &str) { + rbml_w.wr_tagged_str(tag_crate_disambiguator, crate_disambiguator); +} + fn encode_crate_triple(rbml_w: &mut Encoder, triple: &str) { rbml_w.wr_tagged_str(tag_crate_triple, triple); } @@ -1987,6 +1991,7 @@ struct Stats { encode_crate_name(rbml_w, &ecx.link_meta.crate_name); encode_crate_triple(rbml_w, &ecx.tcx.sess.opts.target_triple); encode_hash(rbml_w, &ecx.link_meta.crate_hash); + encode_crate_disambiguator(rbml_w, &ecx.tcx.sess.crate_disambiguator.borrow()); encode_dylib_dependency_formats(rbml_w, &ecx); let mut i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap(); diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 20fc74caad9..01ef33637d5 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -189,7 +189,7 @@ pub fn build_link_meta(sess: &Session, -> LinkMeta { let r = LinkMeta { crate_name: name.to_owned(), - crate_hash: Svh::calculate(&sess.opts.cg.metadata, krate), + crate_hash: Svh::calculate(&sess.crate_disambiguator.borrow()[..], krate), }; info!("{:?}", r); return r; @@ -201,7 +201,7 @@ fn truncated_hash_result(symbol_hasher: &mut Sha256) -> String { output[.. 8].to_hex().to_string() } -pub fn def_to_string(_tcx: &ty::ctxt, did: DefId) -> String { +pub fn def_to_string(_tcx: &TyCtxt, did: DefId) -> String { format!("{}:{}", did.krate, did.index.as_usize()) } @@ -218,9 +218,7 @@ fn symbol_hash<'tcx>(tcx: &TyCtxt<'tcx>, symbol_hasher.input_str(&link_meta.crate_name); symbol_hasher.input_str("-"); symbol_hasher.input_str(link_meta.crate_hash.as_str()); - for meta in tcx.sess.crate_metadata.borrow().iter() { - symbol_hasher.input_str(&meta[..]); - } + symbol_hasher.input_str(&tcx.sess.crate_disambiguator.borrow()[..]); symbol_hasher.input_str("-"); symbol_hasher.input(&tcx.sess.cstore.encode_type(tcx, t, def_to_string)); // Prefix with 'h' so that it never blends into adjacent digits -- 2.44.0