about summary refs log tree commit diff
path: root/compiler/rustc_codegen_cranelift/src/metadata.rs
blob: 1c8fd0b01d9d94ed346e67bf5ae734bb9d12b50b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//! Writing of the rustc metadata for dylibs

use object::write::{Object, StandardSegment, Symbol, SymbolSection};
use object::{SectionKind, SymbolFlags, SymbolKind, SymbolScope};

use rustc_metadata::EncodedMetadata;
use rustc_middle::ty::TyCtxt;

// Adapted from https://github.com/rust-lang/rust/blob/da573206f87b5510de4b0ee1a9c044127e409bd3/src/librustc_codegen_llvm/base.rs#L47-L112
pub(crate) fn new_metadata_object(
    tcx: TyCtxt<'_>,
    cgu_name: &str,
    metadata: &EncodedMetadata,
) -> Vec<u8> {
    use snap::write::FrameEncoder;
    use std::io::Write;

    let mut compressed = rustc_metadata::METADATA_HEADER.to_vec();
    FrameEncoder::new(&mut compressed).write_all(metadata.raw_data()).unwrap();

    let triple = crate::target_triple(tcx.sess);

    let binary_format = match triple.binary_format {
        target_lexicon::BinaryFormat::Elf => object::BinaryFormat::Elf,
        target_lexicon::BinaryFormat::Coff => object::BinaryFormat::Coff,
        target_lexicon::BinaryFormat::Macho => object::BinaryFormat::MachO,
        binary_format => tcx.sess.fatal(&format!("binary format {} is unsupported", binary_format)),
    };
    let architecture = match triple.architecture {
        target_lexicon::Architecture::Aarch64(_) => object::Architecture::Aarch64,
        target_lexicon::Architecture::Arm(_) => object::Architecture::Arm,
        target_lexicon::Architecture::Avr => object::Architecture::Avr,
        target_lexicon::Architecture::Hexagon => object::Architecture::Hexagon,
        target_lexicon::Architecture::Mips32(_) => object::Architecture::Mips,
        target_lexicon::Architecture::Mips64(_) => object::Architecture::Mips64,
        target_lexicon::Architecture::Msp430 => object::Architecture::Msp430,
        target_lexicon::Architecture::Powerpc => object::Architecture::PowerPc,
        target_lexicon::Architecture::Powerpc64 => object::Architecture::PowerPc64,
        target_lexicon::Architecture::Powerpc64le => todo!(),
        target_lexicon::Architecture::Riscv32(_) => object::Architecture::Riscv32,
        target_lexicon::Architecture::Riscv64(_) => object::Architecture::Riscv64,
        target_lexicon::Architecture::S390x => object::Architecture::S390x,
        target_lexicon::Architecture::Sparc64 => object::Architecture::Sparc64,
        target_lexicon::Architecture::Sparcv9 => object::Architecture::Sparc64,
        target_lexicon::Architecture::X86_32(_) => object::Architecture::I386,
        target_lexicon::Architecture::X86_64 => object::Architecture::X86_64,
        architecture => {
            tcx.sess.fatal(&format!("target architecture {:?} is unsupported", architecture,))
        }
    };
    let endian = match triple.endianness().unwrap() {
        target_lexicon::Endianness::Little => object::Endianness::Little,
        target_lexicon::Endianness::Big => object::Endianness::Big,
    };

    let mut object = Object::new(binary_format, architecture, endian);
    object.add_file_symbol(cgu_name.as_bytes().to_vec());

    let segment = object.segment_name(StandardSegment::Data).to_vec();
    let section_id = object.add_section(segment, b".rustc".to_vec(), SectionKind::Data);
    let offset = object.append_section_data(section_id, &compressed, 1);
    // For MachO and probably PE this is necessary to prevent the linker from throwing away the
    // .rustc section. For ELF this isn't necessary, but it also doesn't harm.
    object.add_symbol(Symbol {
        name: rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx).into_bytes(),
        value: offset,
        size: compressed.len() as u64,
        kind: SymbolKind::Data,
        scope: SymbolScope::Dynamic,
        weak: false,
        section: SymbolSection::Section(section_id),
        flags: SymbolFlags::None,
    });

    object.write().unwrap()
}