(index<- )        ./librustc/metadata/loader.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri May  9 13:02:28 2014
   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, mHashSet<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(arArchiveRO) -> 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(osOs, 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(osOs, 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(osOs) -> &'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(osOs) -> &'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(osOs, 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:- 7
565: 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:- 4
librustc/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:- 6
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() });


librustc/metadata/loader.rs:66:1-66:1 -struct- definition:
pub struct Context<'a> {
    pub sess: &'a Session,
    pub span: Span,
references:- 3
111: 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:- 6
254:                 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:- 2
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),


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:- 4
452: 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:- 6
librustc/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:- 2
librustc/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:                 }