1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Finds crate binaries and loads their metadata
12
13 use back::archive::{ArchiveRO, METADATA_FILENAME};
14 use back::svh::Svh;
15 use driver::session::Session;
16 use lib::llvm::{False, llvm, ObjectFile, mk_section_iter};
17 use metadata::cstore::{MetadataBlob, MetadataVec, MetadataArchive};
18 use metadata::decoder;
19 use metadata::encoder;
20 use metadata::filesearch::{FileSearch, FileMatches, FileDoesntMatch};
21 use syntax::codemap::Span;
22 use syntax::diagnostic::SpanHandler;
23 use syntax::crateid::CrateId;
24 use syntax::attr::AttrMetaMethods;
25 use util::fs;
26
27 use std::c_str::ToCStr;
28 use std::cast;
29 use std::cmp;
30 use std::io;
31 use std::ptr;
32 use std::slice;
33 use std::str;
34
35 use collections::{HashMap, HashSet};
36 use flate;
37 use time;
38
39 pub static MACOS_DLL_PREFIX: &'static str = "lib";
40 pub static MACOS_DLL_SUFFIX: &'static str = ".dylib";
41
42 pub static WIN32_DLL_PREFIX: &'static str = "";
43 pub static WIN32_DLL_SUFFIX: &'static str = ".dll";
44
45 pub static LINUX_DLL_PREFIX: &'static str = "lib";
46 pub static LINUX_DLL_SUFFIX: &'static str = ".so";
47
48 pub static FREEBSD_DLL_PREFIX: &'static str = "lib";
49 pub static FREEBSD_DLL_SUFFIX: &'static str = ".so";
50
51 pub static ANDROID_DLL_PREFIX: &'static str = "lib";
52 pub static ANDROID_DLL_SUFFIX: &'static str = ".so";
53
54 pub enum Os {
55 OsMacos,
56 OsWin32,
57 OsLinux,
58 OsAndroid,
59 OsFreebsd
60 }
61
62 pub struct CrateMismatch {
63 path: Path,
64 got: ~str,
65 }
66
67 pub struct Context<'a> {
68 pub sess: &'a Session,
69 pub span: Span,
70 pub ident: &'a str,
71 pub crate_id: &'a CrateId,
72 pub id_hash: &'a str,
73 pub hash: Option<&'a Svh>,
74 pub triple: &'a str,
75 pub os: Os,
76 pub filesearch: FileSearch<'a>,
77 pub root: &'a Option<CratePaths>,
78 pub rejected_via_hash: Vec<CrateMismatch>,
79 pub rejected_via_triple: Vec<CrateMismatch>,
80 }
81
82 pub struct Library {
83 pub dylib: Option<Path>,
84 pub rlib: Option<Path>,
85 pub metadata: MetadataBlob,
86 }
87
88 pub struct ArchiveMetadata {
89 archive: ArchiveRO,
90 // See comments in ArchiveMetadata::new for why this is static
91 data: &'static [u8],
92 }
93
94 pub struct CratePaths {
95 pub ident: ~str,
96 pub dylib: Option<Path>,
97 pub rlib: Option<Path>
98 }
99
100 impl CratePaths {
101 fn paths(&self) -> Vec<Path> {
102 match (&self.dylib, &self.rlib) {
103 (&None, &None) => vec!(),
104 (&Some(ref p), &None) |
105 (&None, &Some(ref p)) => vec!(p.clone()),
106 (&Some(ref p1), &Some(ref p2)) => vec!(p1.clone(), p2.clone()),
107 }
108 }
109 }
110
111 impl<'a> Context<'a> {
112 pub fn maybe_load_library_crate(&mut self) -> Option<Library> {
113 self.find_library_crate()
114 }
115
116 pub fn load_library_crate(&mut self) -> Library {
117 match self.find_library_crate() {
118 Some(t) => t,
119 None => {
120 self.report_load_errs();
121 unreachable!()
122 }
123 }
124 }
125
126 pub fn report_load_errs(&mut self) {
127 let message = if self.rejected_via_hash.len() > 0 {
128 format!("found possibly newer version of crate `{}`",
129 self.ident)
130 } else if self.rejected_via_triple.len() > 0 {
131 format!("found incorrect triple for crate `{}`", self.ident)
132 } else {
133 format!("can't find crate for `{}`", self.ident)
134 };
135 let message = match self.root {
136 &None => message,
137 &Some(ref r) => format!("{} which `{}` depends on",
138 message, r.ident)
139 };
140 self.sess.span_err(self.span, message);
141
142 let mismatches = self.rejected_via_triple.iter();
143 if self.rejected_via_triple.len() > 0 {
144 self.sess.span_note(self.span, format!("expected triple of {}", self.triple));
145 for (i, &CrateMismatch{ ref path, ref got }) in mismatches.enumerate() {
146 self.sess.fileline_note(self.span,
147 format!("crate `{}` path \\#{}, triple {}: {}",
148 self.ident, i+1, got, path.display()));
149 }
150 }
151 if self.rejected_via_hash.len() > 0 {
152 self.sess.span_note(self.span, "perhaps this crate needs \
153 to be recompiled?");
154 let mismatches = self.rejected_via_hash.iter();
155 for (i, &CrateMismatch{ ref path, .. }) in mismatches.enumerate() {
156 self.sess.fileline_note(self.span,
157 format!("crate `{}` path \\#{}: {}",
158 self.ident, i+1, path.display()));
159 }
160 match self.root {
161 &None => {}
162 &Some(ref r) => {
163 for (i, path) in r.paths().iter().enumerate() {
164 self.sess.fileline_note(self.span,
165 format!("crate `{}` path \\#{}: {}",
166 r.ident, i+1, path.display()));
167 }
168 }
169 }
170 }
171 self.sess.abort_if_errors();
172 }
173
174 fn find_library_crate(&mut self) -> Option<Library> {
175 let (dyprefix, dysuffix) = self.dylibname();
176
177 // want: crate_name.dir_part() + prefix + crate_name.file_part + "-"
178 let dylib_prefix = format!("{}{}-", dyprefix, self.crate_id.name);
179 let rlib_prefix = format!("lib{}-", self.crate_id.name);
180
181 let mut candidates = HashMap::new();
182
183 // First, find all possible candidate rlibs and dylibs purely based on
184 // the name of the files themselves. We're trying to match against an
185 // exact crate_id and a possibly an exact hash.
186 //
187 // During this step, we can filter all found libraries based on the
188 // name and id found in the crate id (we ignore the path portion for
189 // filename matching), as well as the exact hash (if specified). If we
190 // end up having many candidates, we must look at the metadata to
191 // perform exact matches against hashes/crate ids. Note that opening up
192 // the metadata is where we do an exact match against the full contents
193 // of the crate id (path/name/id).
194 //
195 // The goal of this step is to look at as little metadata as possible.
196 self.filesearch.search(|path| {
197 let file = match path.filename_str() {
198 None => return FileDoesntMatch,
199 Some(file) => file,
200 };
201 if file.starts_with(rlib_prefix) && file.ends_with(".rlib") {
202 info!("rlib candidate: {}", path.display());
203 match self.try_match(file, rlib_prefix, ".rlib") {
204 Some(hash) => {
205 info!("rlib accepted, hash: {}", hash);
206 let slot = candidates.find_or_insert_with(hash, |_| {
207 (HashSet::new(), HashSet::new())
208 });
209 let (ref mut rlibs, _) = *slot;
210 rlibs.insert(fs::realpath(path).unwrap());
211 FileMatches
212 }
213 None => {
214 info!("rlib rejected");
215 FileDoesntMatch
216 }
217 }
218 } else if file.starts_with(dylib_prefix) && file.ends_with(dysuffix){
219 info!("dylib candidate: {}", path.display());
220 match self.try_match(file, dylib_prefix, dysuffix) {
221 Some(hash) => {
222 info!("dylib accepted, hash: {}", hash);
223 let slot = candidates.find_or_insert_with(hash, |_| {
224 (HashSet::new(), HashSet::new())
225 });
226 let (_, ref mut dylibs) = *slot;
227 dylibs.insert(fs::realpath(path).unwrap());
228 FileMatches
229 }
230 None => {
231 info!("dylib rejected");
232 FileDoesntMatch
233 }
234 }
235 } else {
236 FileDoesntMatch
237 }
238 });
239
240 // We have now collected all known libraries into a set of candidates
241 // keyed of the filename hash listed. For each filename, we also have a
242 // list of rlibs/dylibs that apply. Here, we map each of these lists
243 // (per hash), to a Library candidate for returning.
244 //
245 // A Library candidate is created if the metadata for the set of
246 // libraries corresponds to the crate id and hash criteria that this
247 // search is being performed for.
248 let mut libraries = Vec::new();
249 for (_hash, (rlibs, dylibs)) in candidates.move_iter() {
250 let mut metadata = None;
251 let rlib = self.extract_one(rlibs, "rlib", &mut metadata);
252 let dylib = self.extract_one(dylibs, "dylib", &mut metadata);
253 match metadata {
254 Some(metadata) => {
255 libraries.push(Library {
256 dylib: dylib,
257 rlib: rlib,
258 metadata: metadata,
259 })
260 }
261 None => {}
262 }
263 }
264
265 // Having now translated all relevant found hashes into libraries, see
266 // what we've got and figure out if we found multiple candidates for
267 // libraries or not.
268 match libraries.len() {
269 0 => None,
270 1 => Some(libraries.move_iter().next().unwrap()),
271 _ => {
272 self.sess.span_err(self.span,
273 format!("multiple matching crates for `{}`",
274 self.crate_id.name));
275 self.sess.note("candidates:");
276 for lib in libraries.iter() {
277 match lib.dylib {
278 Some(ref p) => {
279 self.sess.note(format!("path: {}", p.display()));
280 }
281 None => {}
282 }
283 match lib.rlib {
284 Some(ref p) => {
285 self.sess.note(format!("path: {}", p.display()));
286 }
287 None => {}
288 }
289 let data = lib.metadata.as_slice();
290 let crate_id = decoder::get_crate_id(data);
291 note_crateid_attr(self.sess.diagnostic(), &crate_id);
292 }
293 None
294 }
295 }
296 }
297
298 // Attempts to match the requested version of a library against the file
299 // specified. The prefix/suffix are specified (disambiguates between
300 // rlib/dylib).
301 //
302 // The return value is `None` if `file` doesn't look like a rust-generated
303 // library, or if a specific version was requested and it doesn't match the
304 // apparent file's version.
305 //
306 // If everything checks out, then `Some(hash)` is returned where `hash` is
307 // the listed hash in the filename itself.
308 fn try_match(&self, file: &str, prefix: &str, suffix: &str) -> Option<~str>{
309 let middle = file.slice(prefix.len(), file.len() - suffix.len());
310 debug!("matching -- {}, middle: {}", file, middle);
311 let mut parts = middle.splitn('-', 1);
312 let hash = match parts.next() { Some(h) => h, None => return None };
313 debug!("matching -- {}, hash: {} (want {})", file, hash, self.id_hash);
314 let vers = match parts.next() { Some(v) => v, None => return None };
315 debug!("matching -- {}, vers: {} (want {})", file, vers,
316 self.crate_id.version);
317 match self.crate_id.version {
318 Some(ref version) if version.as_slice() != vers => return None,
319 Some(..) => {} // check the hash
320
321 // hash is irrelevant, no version specified
322 None => return Some(hash.to_owned())
323 }
324 debug!("matching -- {}, vers ok", file);
325 // hashes in filenames are prefixes of the "true hash"
326 if self.id_hash == hash.as_slice() {
327 debug!("matching -- {}, hash ok", file);
328 Some(hash.to_owned())
329 } else {
330 None
331 }
332 }
333
334 // Attempts to extract *one* library from the set `m`. If the set has no
335 // elements, `None` is returned. If the set has more than one element, then
336 // the errors and notes are emitted about the set of libraries.
337 //
338 // With only one library in the set, this function will extract it, and then
339 // read the metadata from it if `*slot` is `None`. If the metadata couldn't
340 // be read, it is assumed that the file isn't a valid rust library (no
341 // errors are emitted).
342 fn extract_one(&mut self, m: HashSet<Path>, flavor: &str,
343 slot: &mut Option<MetadataBlob>) -> Option<Path> {
344 let mut ret = None::<Path>;
345 let mut error = 0;
346
347 if slot.is_some() {
348 // FIXME(#10786): for an optimization, we only read one of the
349 // library's metadata sections. In theory we should
350 // read both, but reading dylib metadata is quite
351 // slow.
352 if m.len() == 0 {
353 return None
354 } else if m.len() == 1 {
355 return Some(m.move_iter().next().unwrap())
356 }
357 }
358
359 for lib in m.move_iter() {
360 info!("{} reading metadata from: {}", flavor, lib.display());
361 let metadata = match get_metadata_section(self.os, &lib) {
362 Ok(blob) => {
363 if self.crate_matches(blob.as_slice(), &lib) {
364 blob
365 } else {
366 info!("metadata mismatch");
367 continue
368 }
369 }
370 Err(_) => {
371 info!("no metadata found");
372 continue
373 }
374 };
375 if ret.is_some() {
376 self.sess.span_err(self.span,
377 format!("multiple {} candidates for `{}` \
378 found", flavor, self.crate_id.name));
379 self.sess.span_note(self.span,
380 format!(r"candidate \#1: {}",
381 ret.get_ref().display()));
382 error = 1;
383 ret = None;
384 }
385 if error > 0 {
386 error += 1;
387 self.sess.span_note(self.span,
388 format!(r"candidate \#{}: {}", error,
389 lib.display()));
390 continue
391 }
392 *slot = Some(metadata);
393 ret = Some(lib);
394 }
395 return if error > 0 {None} else {ret}
396 }
397
398 fn crate_matches(&mut self, crate_data: &[u8], libpath: &Path) -> bool {
399 match decoder::maybe_get_crate_id(crate_data) {
400 Some(ref id) if self.crate_id.matches(id) => {}
401 _ => { info!("Rejecting via crate_id"); return false }
402 }
403 let hash = match decoder::maybe_get_crate_hash(crate_data) {
404 Some(hash) => hash, None => {
405 info!("Rejecting via lack of crate hash");
406 return false;
407 }
408 };
409
410 let triple = decoder::get_crate_triple(crate_data);
411 if triple.as_slice() != self.triple {
412 info!("Rejecting via crate triple: expected {} got {}", self.triple, triple);
413 self.rejected_via_triple.push(CrateMismatch{ path: libpath.clone(),
414 got: triple.to_owned() });
415 return false;
416 }
417
418 match self.hash {
419 None => true,
420 Some(myhash) => {
421 if *myhash != hash {
422 info!("Rejecting via hash: expected {} got {}", *myhash, hash);
423 self.rejected_via_hash.push(CrateMismatch{ path: libpath.clone(),
424 got: myhash.as_str().to_owned() });
425 false
426 } else {
427 true
428 }
429 }
430 }
431 }
432
433
434 // Returns the corresponding (prefix, suffix) that files need to have for
435 // dynamic libraries
436 fn dylibname(&self) -> (&'static str, &'static str) {
437 match self.os {
438 OsWin32 => (WIN32_DLL_PREFIX, WIN32_DLL_SUFFIX),
439 OsMacos => (MACOS_DLL_PREFIX, MACOS_DLL_SUFFIX),
440 OsLinux => (LINUX_DLL_PREFIX, LINUX_DLL_SUFFIX),
441 OsAndroid => (ANDROID_DLL_PREFIX, ANDROID_DLL_SUFFIX),
442 OsFreebsd => (FREEBSD_DLL_PREFIX, FREEBSD_DLL_SUFFIX),
443 }
444 }
445
446 }
447
448 pub fn note_crateid_attr(diag: &SpanHandler, crateid: &CrateId) {
449 diag.handler().note(format!("crate_id: {}", crateid.to_str()));
450 }
451
452 impl ArchiveMetadata {
453 fn new(ar: ArchiveRO) -> Option<ArchiveMetadata> {
454 let data: &'static [u8] = {
455 let data = match ar.read(METADATA_FILENAME) {
456 Some(data) => data,
457 None => {
458 debug!("didn't find '{}' in the archive", METADATA_FILENAME);
459 return None;
460 }
461 };
462 // This data is actually a pointer inside of the archive itself, but
463 // we essentially want to cache it because the lookup inside the
464 // archive is a fairly expensive operation (and it's queried for
465 // *very* frequently). For this reason, we transmute it to the
466 // static lifetime to put into the struct. Note that the buffer is
467 // never actually handed out with a static lifetime, but rather the
468 // buffer is loaned with the lifetime of this containing object.
469 // Hence, we're guaranteed that the buffer will never be used after
470 // this object is dead, so this is a safe operation to transmute and
471 // store the data as a static buffer.
472 unsafe { cast::transmute(data) }
473 };
474 Some(ArchiveMetadata {
475 archive: ar,
476 data: data,
477 })
478 }
479
480 pub fn as_slice<'a>(&'a self) -> &'a [u8] { self.data }
481 }
482
483 // Just a small wrapper to time how long reading metadata takes.
484 fn get_metadata_section(os: Os, filename: &Path) -> Result<MetadataBlob, ~str> {
485 let start = time::precise_time_ns();
486 let ret = get_metadata_section_imp(os, filename);
487 info!("reading {} => {}ms", filename.filename_display(),
488 (time::precise_time_ns() - start) / 1000000);
489 return ret;
490 }
491
492 fn get_metadata_section_imp(os: Os, filename: &Path) -> Result<MetadataBlob, ~str> {
493 if !filename.exists() {
494 return Err(format!("no such file: '{}'", filename.display()));
495 }
496 if filename.filename_str().unwrap().ends_with(".rlib") {
497 // Use ArchiveRO for speed here, it's backed by LLVM and uses mmap
498 // internally to read the file. We also avoid even using a memcpy by
499 // just keeping the archive along while the metadata is in use.
500 let archive = match ArchiveRO::open(filename) {
501 Some(ar) => ar,
502 None => {
503 debug!("llvm didn't like `{}`", filename.display());
504 return Err(format!("failed to read rlib metadata: '{}'",
505 filename.display()));
506 }
507 };
508 return match ArchiveMetadata::new(archive).map(|ar| MetadataArchive(ar)) {
509 None => return Err(format!("failed to read rlib metadata: '{}'",
510 filename.display())),
511 Some(blob) => return Ok(blob)
512 }
513 }
514 unsafe {
515 let mb = filename.with_c_str(|buf| {
516 llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
517 });
518 if mb as int == 0 {
519 return Err(format!("error reading library: '{}'",filename.display()))
520 }
521 let of = match ObjectFile::new(mb) {
522 Some(of) => of,
523 _ => return Err(format!("provided path not an object file: '{}'", filename.display()))
524 };
525 let si = mk_section_iter(of.llof);
526 while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
527 let mut name_buf = ptr::null();
528 let name_len = llvm::LLVMRustGetSectionName(si.llsi, &mut name_buf);
529 let name = str::raw::from_buf_len(name_buf as *u8, name_len as uint);
530 debug!("get_metadata_section: name {}", name);
531 if read_meta_section_name(os) == name {
532 let cbuf = llvm::LLVMGetSectionContents(si.llsi);
533 let csz = llvm::LLVMGetSectionSize(si.llsi) as uint;
534 let mut found = Err(format!("metadata not found: '{}'", filename.display()));
535 let cvbuf: *u8 = cast::transmute(cbuf);
536 let vlen = encoder::metadata_encoding_version.len();
537 debug!("checking {} bytes of metadata-version stamp",
538 vlen);
539 let minsz = cmp::min(vlen, csz);
540 let version_ok = slice::raw::buf_as_slice(cvbuf, minsz,
541 |buf0| buf0 == encoder::metadata_encoding_version);
542 if !version_ok { return Err(format!("incompatible metadata version found: '{}'",
543 filename.display())); }
544
545 let cvbuf1 = cvbuf.offset(vlen as int);
546 debug!("inflating {} bytes of compressed metadata",
547 csz - vlen);
548 slice::raw::buf_as_slice(cvbuf1, csz-vlen, |bytes| {
549 match flate::inflate_bytes(bytes) {
550 Some(inflated) => found = Ok(MetadataVec(inflated)),
551 None => found = Err(format!("failed to decompress metadata for: '{}'",
552 filename.display()))
553 }
554 });
555 if found.is_ok() {
556 return found;
557 }
558 }
559 llvm::LLVMMoveToNextSection(si.llsi);
560 }
561 return Err(format!("metadata not found: '{}'", filename.display()));
562 }
563 }
564
565 pub fn meta_section_name(os: Os) -> &'static str {
566 match os {
567 OsMacos => "__DATA,__note.rustc",
568 OsWin32 => ".note.rustc",
569 OsLinux => ".note.rustc",
570 OsAndroid => ".note.rustc",
571 OsFreebsd => ".note.rustc"
572 }
573 }
574
575 pub fn read_meta_section_name(os: Os) -> &'static str {
576 match os {
577 OsMacos => "__note.rustc",
578 OsWin32 => ".note.rustc",
579 OsLinux => ".note.rustc",
580 OsAndroid => ".note.rustc",
581 OsFreebsd => ".note.rustc"
582 }
583 }
584
585 // A diagnostic function for dumping crate metadata to an output stream
586 pub fn list_file_metadata(os: Os, path: &Path,
587 out: &mut io::Writer) -> io::IoResult<()> {
588 match get_metadata_section(os, path) {
589 Ok(bytes) => decoder::list_crate_metadata(bytes.as_slice(), out),
590 Err(msg) => {
591 write!(out, "{}\n", msg)
592 }
593 }
594 }
librustc/metadata/loader.rs:53:1-53:1 -enum- definition:
pub enum Os {
OsMacos,
OsWin32,
references:- 7565: pub fn meta_section_name(os: Os) -> &'static str {
566: match os {
--
585: // A diagnostic function for dumping crate metadata to an output stream
586: pub fn list_file_metadata(os: Os, path: &Path,
587: out: &mut io::Writer) -> io::IoResult<()> {
librustc/driver/session.rs:
537: pub fn sess_os_to_meta_os(os: abi::Os) -> metadata::loader::Os {
538: use metadata::loader;
librustc/metadata/loader.rs:
575: pub fn read_meta_section_name(os: Os) -> &'static str {
576: match os {
librustc/metadata/loader.rs:564:1-564:1 -fn- definition:
pub fn meta_section_name(os: Os) -> &'static str {
match os {
OsMacos => "__DATA,__note.rustc",
references:- 4librustc/back/mips.rs:
20: meta_sect_name: meta_section_name(sess_os_to_meta_os(target_os)).to_owned(),
librustc/back/x86.rs:
21: meta_sect_name: meta_section_name(sess_os_to_meta_os(target_os)).to_owned(),
librustc/back/x86_64.rs:
21: meta_sect_name: meta_section_name(sess_os_to_meta_os(target_os)).to_owned(),
librustc/back/arm.rs:
25: meta_sect_name: meta_section_name(sess_os_to_meta_os(target_os)).to_owned(),
librustc/metadata/loader.rs:61:1-61:1 -struct- definition:
pub struct CrateMismatch {
path: Path,
got: ~str,
references:- 6422: info!("Rejecting via hash: expected {} got {}", *myhash, hash);
423: self.rejected_via_hash.push(CrateMismatch{ path: libpath.clone(),
424: got: myhash.as_str().to_owned() });
librustc/metadata/loader.rs:66:1-66:1 -struct- definition:
pub struct Context<'a> {
pub sess: &'a Session,
pub span: Span,
references:- 3111: impl<'a> Context<'a> {
112: pub fn maybe_load_library_crate(&mut self) -> Option<Library> {
librustc/metadata/creader.rs:
325: let id_hash = link::crate_id_hash(crate_id);
326: let mut load_ctxt = loader::Context {
327: sess: e.sess,
--
390: let os = driver::get_os(driver::host_triple()).unwrap();
391: let mut load_ctxt = loader::Context {
392: sess: self.env.sess,
librustc/metadata/loader.rs:81:1-81:1 -struct- definition:
pub struct Library {
pub dylib: Option<Path>,
pub rlib: Option<Path>,
references:- 6254: Some(metadata) => {
255: libraries.push(Library {
256: dylib: dylib,
librustc/metadata/creader.rs:
294: let loader::Library{ dylib, rlib, metadata } = lib;
librustc/metadata/loader.rs:
174: fn find_library_crate(&mut self) -> Option<Library> {
175: let (dyprefix, dysuffix) = self.dylibname();
librustc/metadata/loader.rs:483:65-483:65 -fn- definition:
// Just a small wrapper to time how long reading metadata takes.
fn get_metadata_section(os: Os, filename: &Path) -> Result<MetadataBlob, ~str> {
let start = time::precise_time_ns();
references:- 2587: out: &mut io::Writer) -> io::IoResult<()> {
588: match get_metadata_section(os, path) {
589: Ok(bytes) => decoder::list_crate_metadata(bytes.as_slice(), out),
librustc/metadata/loader.rs:87:1-87:1 -struct- definition:
pub struct ArchiveMetadata {
archive: ArchiveRO,
// See comments in ArchiveMetadata::new for why this is static
references:- 4452: impl ArchiveMetadata {
453: fn new(ar: ArchiveRO) -> Option<ArchiveMetadata> {
454: let data: &'static [u8] = {
librustc/metadata/cstore.rs:
36: MetadataVec(CVec<u8>),
37: MetadataArchive(loader::ArchiveMetadata),
38: }
librustc/metadata/loader.rs:
473: };
474: Some(ArchiveMetadata {
475: archive: ar,
librustc/metadata/loader.rs:93:1-93:1 -struct- definition:
pub struct CratePaths {
pub ident: ~str,
pub dylib: Option<Path>,
references:- 6librustc/metadata/creader.rs:
280: let crate_paths = if root.is_none() {
281: Some(CratePaths {
282: ident: ident.to_owned(),
librustc/metadata/loader.rs:
76: pub filesearch: FileSearch<'a>,
77: pub root: &'a Option<CratePaths>,
78: pub rejected_via_hash: Vec<CrateMismatch>,
librustc/metadata/creader.rs:
267: fn register_crate<'a>(e: &mut Env,
268: root: &Option<CratePaths>,
269: ident: &str,
--
315: fn resolve_crate<'a>(e: &mut Env,
316: root: &Option<CratePaths>,
317: ident: &str,
--
350: fn resolve_crate_deps(e: &mut Env,
351: root: &Option<CratePaths>,
352: cdata: &[u8], span : Span)
librustc/metadata/loader.rs:
100: impl CratePaths {
101: fn paths(&self) -> Vec<Path> {
librustc/metadata/loader.rs:447:1-447:1 -fn- definition:
pub fn note_crateid_attr(diag: &SpanHandler, crateid: &CrateId) {
diag.handler().note(format!("crate_id: {}", crateid.to_str()));
}
references:- 2librustc/metadata/creader.rs:
92: diag.span_note(data.span, "used here");
93: loader::note_crateid_attr(diag, &data.crate_id());
94: }
librustc/metadata/loader.rs:
290: let crate_id = decoder::get_crate_id(data);
291: note_crateid_attr(self.sess.diagnostic(), &crate_id);
292: }