//! Reading of the rustc metadata for rlibs and dylibs

use std::borrow::Cow;
use std::fs::File;
use std::io::Write;
use std::path::Path;

use itertools::Itertools;
use object::write::{self, StandardSegment, Symbol, SymbolSection};
use object::{
    Architecture, BinaryFormat, Endianness, FileFlags, Object, ObjectSection, ObjectSymbol,
    SectionFlags, SectionKind, SymbolFlags, SymbolKind, SymbolScope, elf, pe, xcoff,
};
use rustc_abi::Endian;
use rustc_data_structures::memmap::Mmap;
use rustc_data_structures::owned_slice::{OwnedSlice, try_slice_owned};
use rustc_metadata::EncodedMetadata;
use rustc_metadata::creader::MetadataLoader;
use rustc_metadata::fs::METADATA_FILENAME;
use rustc_middle::bug;
use rustc_session::Session;
use rustc_span::sym;
use rustc_target::spec::{CfgAbi, LlvmAbi, Os, RelocModel, Target, ef_avr_arch};
use tracing::debug;

use super::apple;

/// The default metadata loader. This is used by cg_llvm and cg_clif.
///
/// # Metadata location
///
/// <dl>
/// <dt>rlib</dt>
/// <dd>The metadata can be found in the `lib.rmeta` file inside of the ar archive.</dd>
/// <dt>dylib</dt>
/// <dd>The metadata can be found in the `.rustc` section of the shared library.</dd>
/// </dl>
#[derive(Debug)]
pub struct DefaultMetadataLoader;

static AIX_METADATA_SYMBOL_NAME: &'static str = "__aix_rust_metadata";

fn load_metadata_with(
    path: &Path,
    f: impl for<'a> FnOnce(&'a [u8]) -> Result<&'a [u8], String>,
) -> Result<OwnedSlice, String> {
    let file =
        File::open(path).map_err(|e| format!("failed to open file '{}': {}", path.display(), e))?;

    unsafe { Mmap::map(file) }
        .map_err(|e| format!("failed to mmap file '{}': {}", path.display(), e))
        .and_then(|mmap| try_slice_owned(mmap, |mmap| f(mmap)))
}

impl MetadataLoader for DefaultMetadataLoader {
    fn get_rlib_metadata(&self, target: &Target, path: &Path) -> Result<OwnedSlice, String> {
        debug!("getting rlib metadata for {}", path.display());
        load_metadata_with(path, |data| {
            let archive = object::read::archive::ArchiveFile::parse(&*data)
                .map_err(|e| format!("failed to parse rlib '{}': {}", path.display(), e))?;

            for entry_result in archive.members() {
                let entry = entry_result
                    .map_err(|e| format!("failed to parse rlib '{}': {}", path.display(), e))?;
                if entry.name() == METADATA_FILENAME.as_bytes() {
                    let data = entry
                        .data(data)
                        .map_err(|e| format!("failed to parse rlib '{}': {}", path.display(), e))?;
                    if target.is_like_aix {
                        return get_metadata_xcoff(path, data);
                    } else {
                        return search_for_section(path, data, ".rmeta");
                    }
                }
            }

            Err(format!("metadata not found in rlib '{}'", path.display()))
        })
    }

    fn get_dylib_metadata(&self, target: &Target, path: &Path) -> Result<OwnedSlice, String> {
        debug!("getting dylib metadata for {}", path.display());
        if target.is_like_aix {
            load_metadata_with(path, |data| {
                let archive = object::read::archive::ArchiveFile::parse(&*data).map_err(|e| {
                    format!("failed to parse aix dylib '{}': {}", path.display(), e)
                })?;

                match archive.members().exactly_one() {
                    Ok(lib) => {
                        let lib = lib.map_err(|e| {
                            format!("failed to parse aix dylib '{}': {}", path.display(), e)
                        })?;
                        let data = lib.data(data).map_err(|e| {
                            format!("failed to parse aix dylib '{}': {}", path.display(), e)
                        })?;
                        get_metadata_xcoff(path, data)
                    }
                    Err(e) => Err(format!("failed to parse aix dylib '{}': {}", path.display(), e)),
                }
            })
        } else {
            load_metadata_with(path, |data| search_for_section(path, data, ".rustc"))
        }
    }
}

pub(super) fn search_for_section<'a>(
    path: &Path,
    bytes: &'a [u8],
    section: &str,
) -> Result<&'a [u8], String> {
    let Ok(file) = object::File::parse(bytes) else {
        // The parse above could fail for odd reasons like corruption, but for
        // now we just interpret it as this target doesn't support metadata
        // emission in object files so the entire byte slice itself is probably
        // a metadata file. Ideally though if necessary we could at least check
        // the prefix of bytes to see if it's an actual metadata object and if
        // not forward the error along here.
        return Ok(bytes);
    };
    file.section_by_name(section)
        .ok_or_else(|| format!("no `{}` section in '{}'", section, path.display()))?
        .data()
        .map_err(|e| format!("failed to read {} section in '{}': {}", section, path.display(), e))
}

fn add_gnu_property_note(
    file: &mut write::Object<'static>,
    architecture: Architecture,
    binary_format: BinaryFormat,
    endianness: Endianness,
) {
    // check bti protection
    if binary_format != BinaryFormat::Elf
        || !matches!(architecture, Architecture::X86_64 | Architecture::Aarch64)
    {
        return;
    }

    let section = file.add_section(
        file.segment_name(StandardSegment::Data).to_vec(),
        b".note.gnu.property".to_vec(),
        SectionKind::Note,
    );
    let mut data: Vec<u8> = Vec::new();
    let n_namsz: u32 = 4; // Size of the n_name field
    let n_descsz: u32 = 16; // Size of the n_desc field
    let n_type: u32 = object::elf::NT_GNU_PROPERTY_TYPE_0; // Type of note descriptor
    let header_values = [n_namsz, n_descsz, n_type];
    header_values.iter().for_each(|v| {
        data.extend_from_slice(&match endianness {
            Endianness::Little => v.to_le_bytes(),
            Endianness::Big => v.to_be_bytes(),
        })
    });
    data.extend_from_slice(b"GNU\0"); // Owner of the program property note
    let pr_type: u32 = match architecture {
        Architecture::X86_64 => object::elf::GNU_PROPERTY_X86_FEATURE_1_AND,
        Architecture::Aarch64 => object::elf::GNU_PROPERTY_AARCH64_FEATURE_1_AND,
        _ => unreachable!(),
    };
    let pr_datasz: u32 = 4; //size of the pr_data field
    let pr_data: u32 = 3; //program property descriptor
    let pr_padding: u32 = 0;
    let property_values = [pr_type, pr_datasz, pr_data, pr_padding];
    property_values.iter().for_each(|v| {
        data.extend_from_slice(&match endianness {
            Endianness::Little => v.to_le_bytes(),
            Endianness::Big => v.to_be_bytes(),
        })
    });
    file.append_section_data(section, &data, 8);
}

pub(super) fn get_metadata_xcoff<'a>(path: &Path, data: &'a [u8]) -> Result<&'a [u8], String> {
    let Ok(file) = object::File::parse(data) else {
        return Ok(data);
    };
    let info_data = search_for_section(path, data, ".info")?;
    if let Some(metadata_symbol) =
        file.symbols().find(|sym| sym.name() == Ok(AIX_METADATA_SYMBOL_NAME))
    {
        let offset = metadata_symbol.address() as usize;
        // The offset specifies the location of rustc metadata in the .info section of XCOFF.
        // Each string stored in .info section of XCOFF is preceded by a 4-byte length field.
        if offset < 4 {
            return Err(format!("Invalid metadata symbol offset: {offset}"));
        }
        // XCOFF format uses big-endian byte order.
        let len = u32::from_be_bytes(info_data[(offset - 4)..offset].try_into().unwrap()) as usize;
        if offset + len > (info_data.len() as usize) {
            return Err(format!(
                "Metadata at offset {offset} with size {len} is beyond .info section"
            ));
        }
        Ok(&info_data[offset..(offset + len)])
    } else {
        Err(format!("Unable to find symbol {AIX_METADATA_SYMBOL_NAME}"))
    }
}

pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static>> {
    let endianness = match sess.target.options.endian {
        Endian::Little => Endianness::Little,
        Endian::Big => Endianness::Big,
    };
    let Some((architecture, sub_architecture)) =
        sess.target.object_architecture(&sess.unstable_target_features)
    else {
        return None;
    };
    let binary_format = sess.target.binary_format.to_object();

    let mut file = write::Object::new(binary_format, architecture, endianness);
    file.set_sub_architecture(sub_architecture);
    if sess.target.is_like_darwin {
        if macho_is_arm64e(&sess.target) {
            file.set_macho_cpu_subtype(
                object::macho::CPU_SUBTYPE_ARM64E | object::macho::CPU_SUBTYPE_PTRAUTH_ABI,
            );
        }

        file.set_macho_build_version(macho_object_build_version_for_target(sess))
    }
    if binary_format == BinaryFormat::Coff {
        // Disable the default mangler to avoid mangling the special "@feat.00" symbol name.
        let original_mangling = file.mangling();
        file.set_mangling(object::write::Mangling::None);

        let mut feature = 0;

        if file.architecture() == object::Architecture::I386 {
            // When linking with /SAFESEH on x86, lld requires that all linker inputs be marked as
            // safe exception handling compatible. Metadata files masquerade as regular COFF
            // objects and are treated as linker inputs, despite containing no actual code. Thus,
            // they still need to be marked as safe exception handling compatible. See #96498.
            // Reference: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
            feature |= 1;
        }

        file.add_symbol(object::write::Symbol {
            name: "@feat.00".into(),
            value: feature,
            size: 0,
            kind: object::SymbolKind::Data,
            scope: object::SymbolScope::Compilation,
            weak: false,
            section: object::write::SymbolSection::Absolute,
            flags: object::SymbolFlags::None,
        });

        file.set_mangling(original_mangling);
    }
    let e_flags = elf_e_flags(architecture, sess);
    // adapted from LLVM's `MCELFObjectTargetWriter::getOSABI`
    let os_abi = elf_os_abi(sess);
    let abi_version = 0;
    add_gnu_property_note(&mut file, architecture, binary_format, endianness);
    file.flags = FileFlags::Elf { os_abi, abi_version, e_flags };
    Some(file)
}

pub(super) fn elf_os_abi(sess: &Session) -> u8 {
    match sess.target.options.os {
        Os::Hermit => elf::ELFOSABI_STANDALONE,
        Os::FreeBsd => elf::ELFOSABI_FREEBSD,
        Os::Solaris => elf::ELFOSABI_SOLARIS,
        _ => elf::ELFOSABI_NONE,
    }
}

pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {
    match architecture {
        Architecture::Mips | Architecture::Mips64 | Architecture::Mips64_N32 => {
            // "N32" indicates an "ILP32" data model on a 64-bit MIPS CPU
            // like SPARC's "v8+", x86_64's "x32", or the watchOS "arm64_32".
            let is_32bit = architecture == Architecture::Mips;
            let mut e_flags = match sess.target.options.cpu.as_ref() {
                "mips1" if is_32bit => elf::EF_MIPS_ARCH_1,
                "mips2" if is_32bit => elf::EF_MIPS_ARCH_2,
                "mips3" => elf::EF_MIPS_ARCH_3,
                "mips4" => elf::EF_MIPS_ARCH_4,
                "mips5" => elf::EF_MIPS_ARCH_5,
                "mips32r2" if is_32bit => elf::EF_MIPS_ARCH_32R2,
                "mips32r6" if is_32bit => elf::EF_MIPS_ARCH_32R6,
                "mips64r2" if !is_32bit => elf::EF_MIPS_ARCH_64R2,
                "mips64r6" if !is_32bit => elf::EF_MIPS_ARCH_64R6,
                s if s.starts_with("mips32") && !is_32bit => {
                    sess.dcx().fatal(format!("invalid CPU `{}` for 64-bit MIPS target", s))
                }
                s if s.starts_with("mips64") && is_32bit => {
                    sess.dcx().fatal(format!("invalid CPU `{}` for 32-bit MIPS target", s))
                }
                _ if is_32bit => elf::EF_MIPS_ARCH_32R2,
                _ => elf::EF_MIPS_ARCH_64R2,
            };

            // Use the explicitly given ABI.
            match &sess.target.options.llvm_abiname {
                LlvmAbi::O32 if is_32bit => e_flags |= elf::EF_MIPS_ABI_O32,
                LlvmAbi::N32 if !is_32bit => e_flags |= elf::EF_MIPS_ABI2,
                LlvmAbi::N64 if !is_32bit => {}
                // The rest is invalid (which is already ensured by the target spec check).
                s => bug!("invalid LLVM ABI `{}` for MIPS target", s),
            };

            if sess.target.options.relocation_model != RelocModel::Static {
                // PIC means position-independent code. CPIC means "calls PIC".
                // CPIC was mutually exclusive with PIC according to
                // the SVR4 MIPS ABI https://refspecs.linuxfoundation.org/elf/mipsabi.pdf
                // and should have only appeared on static objects with dynamically calls.
                // At some point someone (GCC?) decided to set CPIC even for PIC.
                // Nowadays various things expect both set on the same object file
                // and may even error if you mix CPIC and non-CPIC object files,
                // despite that being the entire point of the CPIC ABI extension!
                // As we are in Rome, we do as the Romans do.
                e_flags |= elf::EF_MIPS_PIC | elf::EF_MIPS_CPIC;
            }
            if sess.target.options.cpu.contains("r6") {
                e_flags |= elf::EF_MIPS_NAN2008;
            }
            e_flags
        }
        Architecture::Riscv32 | Architecture::Riscv64 => {
            // Source: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/079772828bd10933d34121117a222b4cc0ee2200/riscv-elf.adoc
            let mut e_flags: u32 = 0x0;

            // Check if compression is enabled
            if sess.target_features.contains(&sym::zca) {
                e_flags |= elf::EF_RISCV_RVC;
            }

            // Check if RVTSO is enabled
            if sess.target_features.contains(&sym::ztso) {
                e_flags |= elf::EF_RISCV_TSO;
            }

            // Set the appropriate flag based on ABI
            // This needs to match LLVM `RISCVELFStreamer.cpp`
            match &sess.target.llvm_abiname {
                LlvmAbi::Ilp32 | LlvmAbi::Lp64 => (),
                LlvmAbi::Ilp32f | LlvmAbi::Lp64f => e_flags |= elf::EF_RISCV_FLOAT_ABI_SINGLE,
                LlvmAbi::Ilp32d | LlvmAbi::Lp64d => e_flags |= elf::EF_RISCV_FLOAT_ABI_DOUBLE,
                // Note that the `lp64e` is still unstable as it's not (yet) part of the ELF psABI.
                LlvmAbi::Ilp32e | LlvmAbi::Lp64e => e_flags |= elf::EF_RISCV_RVE,
                _ => bug!("unknown RISC-V ABI name"),
            }

            e_flags
        }
        Architecture::LoongArch32 | Architecture::LoongArch64 => {
            // Source: https://github.com/loongson/la-abi-specs/blob/release/laelf.adoc#e_flags-identifies-abi-type-and-version
            let mut e_flags: u32 = elf::EF_LARCH_OBJABI_V1;

            // Set the appropriate flag based on ABI
            // This needs to match LLVM `LoongArchELFStreamer.cpp`
            match &sess.target.llvm_abiname {
                LlvmAbi::Ilp32s | LlvmAbi::Lp64s => e_flags |= elf::EF_LARCH_ABI_SOFT_FLOAT,
                LlvmAbi::Ilp32f | LlvmAbi::Lp64f => e_flags |= elf::EF_LARCH_ABI_SINGLE_FLOAT,
                LlvmAbi::Ilp32d | LlvmAbi::Lp64d => e_flags |= elf::EF_LARCH_ABI_DOUBLE_FLOAT,
                _ => bug!("unknown LoongArch ABI name"),
            }

            e_flags
        }
        Architecture::Avr => {
            // Resolve the ISA revision and set
            // the appropriate EF_AVR_ARCH flag.
            if let Some(ref cpu) = sess.opts.cg.target_cpu {
                ef_avr_arch(cpu)
            } else {
                bug!("AVR CPU not explicitly specified")
            }
        }
        Architecture::Csky => {
            if matches!(sess.target.options.cfg_abi, CfgAbi::AbiV2) {
                elf::EF_CSKY_ABIV2
            } else {
                elf::EF_CSKY_ABIV1
            }
        }
        Architecture::PowerPc64 => {
            const EF_PPC64_ABI_UNKNOWN: u32 = 0;
            const EF_PPC64_ABI_ELF_V1: u32 = 1;
            const EF_PPC64_ABI_ELF_V2: u32 = 2;

            match sess.target.options.llvm_abiname {
                // If the flags do not correctly indicate the ABI,
                // linkers such as ld.lld assume that the ppc64 object files are always ELFv2
                // which leads to broken binaries if ELFv1 is used for the object files.
                LlvmAbi::ElfV1 => EF_PPC64_ABI_ELF_V1,
                LlvmAbi::ElfV2 => EF_PPC64_ABI_ELF_V2,
                _ if sess.target.options.binary_format.to_object() == BinaryFormat::Elf => {
                    bug!("invalid ABI specified for this PPC64 ELF target");
                }
                // Fall back
                _ => EF_PPC64_ABI_UNKNOWN,
            }
        }
        Architecture::Sparc32Plus => elf::EF_SPARC_32PLUS,
        _ => 0,
    }
}

/// Mach-O files contain information about:
/// - The platform/OS they were built for (macOS/watchOS/Mac Catalyst/iOS simulator etc).
/// - The minimum OS version / deployment target.
/// - The version of the SDK they were targetting.
///
/// In the past, this was accomplished using the LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS,
/// LC_VERSION_MIN_TVOS or LC_VERSION_MIN_WATCHOS load commands, which each contain information
/// about the deployment target and SDK version, and implicitly, by their presence, which OS they
/// target. Simulator targets were determined if the architecture was x86_64, but there was e.g. a
/// LC_VERSION_MIN_IPHONEOS present.
///
/// This is of course brittle and limited, so modern tooling emit the LC_BUILD_VERSION load
/// command (which contains all three pieces of information in one) when the deployment target is
/// high enough, or the target is something that wouldn't be encodable with the old load commands
/// (such as Mac Catalyst, or Aarch64 iOS simulator).
///
/// Since Xcode 15, Apple's LD apparently requires object files to use this load command, so this
/// returns the `MachOBuildVersion` for the target to do so.
fn macho_object_build_version_for_target(sess: &Session) -> object::write::MachOBuildVersion {
    /// The `object` crate demands "X.Y.Z encoded in nibbles as xxxx.yy.zz"
    /// e.g. minOS 14.0 = 0x000E0000, or SDK 16.2 = 0x00100200
    fn pack_version(apple::OSVersion { major, minor, patch }: apple::OSVersion) -> u32 {
        let (major, minor, patch) = (major as u32, minor as u32, patch as u32);
        (major << 16) | (minor << 8) | patch
    }

    let platform = apple::macho_platform(&sess.target);
    let min_os = sess.apple_deployment_target();

    let mut build_version = object::write::MachOBuildVersion::default();
    build_version.platform = platform;
    build_version.minos = pack_version(min_os);
    // The version here does not _really_ matter, since it is only used at runtime, and we specify
    // it when linking the final binary, so we will omit the version. This is also what LLVM does,
    // and the tooling also allows this (and shows the SDK version as `n/a`). Finally, it is the
    // semantically correct choice, as the SDK has not influenced the binary generated by rustc at
    // this point in time.
    build_version.sdk = 0;

    build_version
}

/// Is Apple's CPU subtype `arm64e`s
fn macho_is_arm64e(target: &Target) -> bool {
    target.llvm_target.starts_with("arm64e")
}

pub(crate) enum MetadataPosition {
    First,
    Last,
}

/// For rlibs we "pack" rustc metadata into a dummy object file.
///
/// Historically it was needed because rustc linked rlibs as whole-archive in some cases.
/// In that case linkers try to include all files located in an archive, so if metadata is stored
/// in an archive then it needs to be of a form that the linker is able to process.
/// Now it's not clear whether metadata still needs to be wrapped into an object file or not.
///
/// Note, though, that we don't actually want this metadata to show up in any
/// final output of the compiler. Instead this is purely for rustc's own
/// metadata tracking purposes.
///
/// With the above in mind, each "flavor" of object format gets special
/// handling here depending on the target:
///
/// * MachO - macos-like targets will insert the metadata into a section that
///   is sort of fake dwarf debug info. Inspecting the source of the macos
///   linker this causes these sections to be skipped automatically because
///   it's not in an allowlist of otherwise well known dwarf section names to
///   go into the final artifact.
///
/// * WebAssembly - this uses wasm files themselves as the object file format
///   so an empty file with no linking metadata but a single custom section is
///   created holding our metadata.
///
/// * COFF - Windows-like targets create an object with a section that has
///   the `IMAGE_SCN_LNK_REMOVE` flag set which ensures that if the linker
///   ever sees the section it doesn't process it and it's removed.
///
/// * ELF - All other targets are similar to Windows in that there's a
///   `SHF_EXCLUDE` flag we can set on sections in an object file to get
///   automatically removed from the final output.
pub(crate) fn create_wrapper_file(
    sess: &Session,
    section_name: String,
    data: &[u8],
) -> (Vec<u8>, MetadataPosition) {
    let Some(mut file) = create_object_file(sess) else {
        if sess.target.is_like_wasm {
            return (
                create_metadata_file_for_wasm(sess, data, &section_name),
                MetadataPosition::First,
            );
        }

        // Targets using this branch don't have support implemented here yet or
        // they're not yet implemented in the `object` crate and will likely
        // fill out this module over time.
        return (data.to_vec(), MetadataPosition::Last);
    };
    let section = if file.format() == BinaryFormat::Xcoff {
        file.add_section(Vec::new(), b".info".to_vec(), SectionKind::Debug)
    } else {
        file.add_section(
            file.segment_name(StandardSegment::Debug).to_vec(),
            section_name.into_bytes(),
            SectionKind::Debug,
        )
    };
    match file.format() {
        BinaryFormat::Coff => {
            file.section_mut(section).flags =
                SectionFlags::Coff { characteristics: pe::IMAGE_SCN_LNK_REMOVE };
        }
        BinaryFormat::Elf => {
            file.section_mut(section).flags =
                SectionFlags::Elf { sh_flags: elf::SHF_EXCLUDE as u64 };
        }
        BinaryFormat::Xcoff => {
            // AIX system linker may aborts if it meets a valid XCOFF file in archive with no .text, no .data and no .bss.
            file.add_section(Vec::new(), b".text".to_vec(), SectionKind::Text);
            file.section_mut(section).flags =
                SectionFlags::Xcoff { s_flags: xcoff::STYP_INFO as u32 };
            // Encode string stored in .info section of XCOFF.
            // FIXME: The length of data here is not guaranteed to fit in a u32.
            // We may have to split the data into multiple pieces in order to
            // store in .info section.
            let len: u32 = data.len().try_into().unwrap();
            let offset = file.append_section_data(section, &len.to_be_bytes(), 1);
            // Add a symbol referring to the data in .info section.
            file.add_symbol(Symbol {
                name: AIX_METADATA_SYMBOL_NAME.into(),
                value: offset + 4,
                size: 0,
                kind: SymbolKind::Unknown,
                scope: SymbolScope::Compilation,
                weak: false,
                section: SymbolSection::Section(section),
                flags: SymbolFlags::Xcoff {
                    n_sclass: xcoff::C_INFO,
                    x_smtyp: xcoff::C_HIDEXT,
                    x_smclas: xcoff::C_HIDEXT,
                    containing_csect: None,
                },
            });
        }
        _ => {}
    };
    file.append_section_data(section, data, 1);
    (file.write().unwrap(), MetadataPosition::First)
}

// Historical note:
//
// When using link.exe it was seen that the section name `.note.rustc`
// was getting shortened to `.note.ru`, and according to the PE and COFF
// specification:
//
// > Executable images do not use a string table and do not support
// > section names longer than 8 characters
//
// https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
//
// As a result, we choose a slightly shorter name! As to why
// `.note.rustc` works on MinGW, see
// https://github.com/llvm/llvm-project/blob/llvmorg-12.0.0/lld/COFF/Writer.cpp#L1190-L1197
pub fn create_compressed_metadata_file(
    sess: &Session,
    metadata: &EncodedMetadata,
    symbol_name: &str,
) -> Vec<u8> {
    let mut packed_metadata = rustc_metadata::METADATA_HEADER.to_vec();
    packed_metadata.write_all(&(metadata.stub_or_full().len() as u64).to_le_bytes()).unwrap();
    packed_metadata.extend(metadata.stub_or_full());

    let Some(mut file) = create_object_file(sess) else {
        if sess.target.is_like_wasm {
            return create_metadata_file_for_wasm(sess, &packed_metadata, ".rustc");
        }
        return packed_metadata.to_vec();
    };
    if file.format() == BinaryFormat::Xcoff {
        return create_compressed_metadata_file_for_xcoff(file, &packed_metadata, symbol_name);
    }
    let section = file.add_section(
        file.segment_name(StandardSegment::Data).to_vec(),
        b".rustc".to_vec(),
        SectionKind::ReadOnlyData,
    );
    match file.format() {
        BinaryFormat::Elf => {
            // Explicitly set no flags to avoid SHF_ALLOC default for data section.
            file.section_mut(section).flags = SectionFlags::Elf { sh_flags: 0 };
        }
        _ => {}
    };
    let offset = file.append_section_data(section, &packed_metadata, 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.
    file.add_symbol(Symbol {
        name: symbol_name.as_bytes().to_vec(),
        value: offset,
        size: packed_metadata.len() as u64,
        kind: SymbolKind::Data,
        scope: SymbolScope::Dynamic,
        weak: false,
        section: SymbolSection::Section(section),
        flags: SymbolFlags::None,
    });

    file.write().unwrap()
}

/// * Xcoff - On AIX, custom sections are merged into predefined sections,
///   so custom .rustc section is not preserved during linking.
///   For this reason, we store metadata in predefined .info section, and
///   define a symbol to reference the metadata. To preserve metadata during
///   linking on AIX, we have to
///   1. Create an empty .text section, a empty .data section.
///   2. Define an empty symbol named `symbol_name` inside .data section.
///   3. Define an symbol named `AIX_METADATA_SYMBOL_NAME` referencing
///      data inside .info section.
///   From XCOFF's view, (2) creates a csect entry in the symbol table, the
///   symbol created by (3) is a info symbol for the preceding csect. Thus
///   two symbols are preserved during linking and we can use the second symbol
///   to reference the metadata.
pub fn create_compressed_metadata_file_for_xcoff(
    mut file: write::Object<'_>,
    data: &[u8],
    symbol_name: &str,
) -> Vec<u8> {
    assert!(file.format() == BinaryFormat::Xcoff);
    // AIX system linker may aborts if it meets a valid XCOFF file in archive with no .text, no .data and no .bss.
    file.add_section(Vec::new(), b".text".to_vec(), SectionKind::Text);
    let data_section = file.add_section(Vec::new(), b".data".to_vec(), SectionKind::Data);
    let section = file.add_section(Vec::new(), b".info".to_vec(), SectionKind::Debug);
    file.add_file_symbol("lib.rmeta".into());
    file.section_mut(section).flags = SectionFlags::Xcoff { s_flags: xcoff::STYP_INFO as u32 };
    // Add a global symbol to data_section.
    file.add_symbol(Symbol {
        name: symbol_name.as_bytes().into(),
        value: 0,
        size: 0,
        kind: SymbolKind::Data,
        scope: SymbolScope::Dynamic,
        weak: true,
        section: SymbolSection::Section(data_section),
        flags: SymbolFlags::None,
    });
    let len: u32 = data.len().try_into().unwrap();
    let offset = file.append_section_data(section, &len.to_be_bytes(), 1);
    // Add a symbol referring to the rustc metadata.
    file.add_symbol(Symbol {
        name: AIX_METADATA_SYMBOL_NAME.into(),
        value: offset + 4, // The metadata is preceded by a 4-byte length field.
        size: 0,
        kind: SymbolKind::Unknown,
        scope: SymbolScope::Dynamic,
        weak: false,
        section: SymbolSection::Section(section),
        flags: SymbolFlags::Xcoff {
            n_sclass: xcoff::C_INFO,
            x_smtyp: xcoff::C_HIDEXT,
            x_smclas: xcoff::C_HIDEXT,
            containing_csect: None,
        },
    });
    file.append_section_data(section, data, 1);
    file.write().unwrap()
}

/// Creates a simple WebAssembly object file, which is itself a wasm module,
/// that contains a custom section of the name `section_name` with contents
/// `data`.
///
/// NB: the `object` crate does not yet have support for writing the wasm
/// object file format. In lieu of that the `wasm-encoder` crate is used to
/// build a wasm file by hand.
///
/// The wasm object file format is defined at
/// <https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md>
/// and mainly consists of a `linking` custom section. In this case the custom
/// section there is empty except for a version marker indicating what format
/// it's in.
///
/// The main purpose of this is to contain a custom section with `section_name`,
/// which is then appended after `linking`.
///
/// As a further detail the object needs to have a 64-bit memory if `wasm64` is
/// the target or otherwise it's interpreted as a 32-bit object which is
/// incompatible with 64-bit ones.
pub fn create_metadata_file_for_wasm(sess: &Session, data: &[u8], section_name: &str) -> Vec<u8> {
    assert!(sess.target.is_like_wasm);
    let mut module = wasm_encoder::Module::new();
    let mut imports = wasm_encoder::ImportSection::new();

    if sess.target.pointer_width == 64 {
        imports.import(
            "env",
            "__linear_memory",
            wasm_encoder::MemoryType {
                minimum: 0,
                maximum: None,
                memory64: true,
                shared: false,
                page_size_log2: None,
            },
        );
    }

    if imports.len() > 0 {
        module.section(&imports);
    }
    module.section(&wasm_encoder::CustomSection {
        name: "linking".into(),
        data: Cow::Borrowed(&[2]),
    });
    module.section(&wasm_encoder::CustomSection { name: section_name.into(), data: data.into() });
    module.finish()
}
