1- use crate :: llvm;
2- use crate :: llvm:: archive_ro:: ArchiveRO ;
3- use crate :: llvm:: { mk_section_iter, False , ObjectFile } ;
4- use rustc_middle:: middle:: cstore:: MetadataLoader ;
51use rustc_target:: spec:: Target ;
62
7- use rustc_codegen_ssa:: METADATA_FILENAME ;
8- use rustc_data_structures:: owning_ref:: OwningRef ;
9- use rustc_data_structures:: rustc_erase_owner;
10- use tracing:: debug;
11-
123use rustc_fs_util:: path_to_c_string;
134use std:: path:: Path ;
145use std:: slice;
156
16- pub use rustc_data_structures:: sync:: MetadataRef ;
17-
18- pub struct LlvmMetadataLoader ;
19-
20- impl MetadataLoader for LlvmMetadataLoader {
21- fn get_rlib_metadata ( & self , _: & Target , filename : & Path ) -> Result < MetadataRef , String > {
22- // Use ArchiveRO for speed here, it's backed by LLVM and uses mmap
23- // internally to read the file. We also avoid even using a memcpy by
24- // just keeping the archive along while the metadata is in use.
25- let archive =
26- ArchiveRO :: open ( filename) . map ( |ar| OwningRef :: new ( Box :: new ( ar) ) ) . map_err ( |e| {
27- debug ! ( "llvm didn't like `{}`: {}" , filename. display( ) , e) ;
28- format ! ( "failed to read rlib metadata in '{}': {}" , filename. display( ) , e)
29- } ) ?;
30- let buf: OwningRef < _ , [ u8 ] > = archive. try_map ( |ar| {
31- ar. iter ( )
32- . filter_map ( |s| s. ok ( ) )
33- . find ( |sect| sect. name ( ) == Some ( METADATA_FILENAME ) )
34- . map ( |s| s. data ( ) )
35- . ok_or_else ( || {
36- debug ! ( "didn't find '{}' in the archive" , METADATA_FILENAME ) ;
37- format ! ( "failed to read rlib metadata: '{}'" , filename. display( ) )
38- } )
39- } ) ?;
40- Ok ( rustc_erase_owner ! ( buf) )
41- }
42-
43- fn get_dylib_metadata ( & self , target : & Target , filename : & Path ) -> Result < MetadataRef , String > {
44- unsafe {
45- let buf = path_to_c_string ( filename) ;
46- let mb = llvm:: LLVMRustCreateMemoryBufferWithContentsOfFile ( buf. as_ptr ( ) )
47- . ok_or_else ( || format ! ( "error reading library: '{}'" , filename. display( ) ) ) ?;
48- let of =
49- ObjectFile :: new ( mb) . map ( |of| OwningRef :: new ( Box :: new ( of) ) ) . ok_or_else ( || {
50- format ! ( "provided path not an object file: '{}'" , filename. display( ) )
51- } ) ?;
52- let buf = of. try_map ( |of| search_meta_section ( of, target, filename) ) ?;
53- Ok ( rustc_erase_owner ! ( buf) )
54- }
55- }
56- }
57-
58- fn search_meta_section < ' a > (
59- of : & ' a ObjectFile ,
60- target : & Target ,
61- filename : & Path ,
62- ) -> Result < & ' a [ u8 ] , String > {
63- unsafe {
64- let si = mk_section_iter ( of. llof ) ;
65- while llvm:: LLVMIsSectionIteratorAtEnd ( of. llof , si. llsi ) == False {
66- let mut name_buf = None ;
67- let name_len = llvm:: LLVMRustGetSectionName ( si. llsi , & mut name_buf) ;
68- let name = name_buf. map_or_else (
69- String :: new, // We got a null ptr, ignore `name_len`.
70- |buf| {
71- String :: from_utf8 (
72- slice:: from_raw_parts ( buf. as_ptr ( ) as * const u8 , name_len as usize )
73- . to_vec ( ) ,
74- )
75- . unwrap ( )
76- } ,
77- ) ;
78- debug ! ( "get_metadata_section: name {}" , name) ;
79- if read_metadata_section_name ( target) == name {
80- let cbuf = llvm:: LLVMGetSectionContents ( si. llsi ) ;
81- let csz = llvm:: LLVMGetSectionSize ( si. llsi ) as usize ;
82- // The buffer is valid while the object file is around
83- let buf: & ' a [ u8 ] = slice:: from_raw_parts ( cbuf as * const u8 , csz) ;
84- return Ok ( buf) ;
85- }
86- llvm:: LLVMMoveToNextSection ( si. llsi ) ;
87- }
88- }
89- Err ( format ! ( "metadata not found: '{}'" , filename. display( ) ) )
90- }
91-
927pub fn metadata_section_name ( target : & Target ) -> & ' static str {
938 // Historical note:
949 //
@@ -106,7 +21,3 @@ pub fn metadata_section_name(target: &Target) -> &'static str {
10621
10722 if target. is_like_osx { "__DATA,.rustc" } else { ".rustc" }
10823}
109-
110- fn read_metadata_section_name ( _target : & Target ) -> & ' static str {
111- ".rustc"
112- }
0 commit comments