//! 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::{Abi, 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(crate) 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);
        }

        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,
            };

            // If the ABI is explicitly given, use it, or default to O32 on 32-bit MIPS,
            // which is the only "true" 32-bit option that LLVM supports.
            match sess.target.options.llvm_abiname.as_ref() {
                "o32" if is_32bit => e_flags |= elf::EF_MIPS_ABI_O32,
                "n32" if !is_32bit => e_flags |= elf::EF_MIPS_ABI2,
                "n64" if !is_32bit => {}
                "" if is_32bit => e_flags |= elf::EF_MIPS_ABI_O32,
                "" => sess.dcx().fatal("LLVM ABI must be specified for 64-bit MIPS targets"),
                s if is_32bit => {
                    sess.dcx().fatal(format!("invalid LLVM ABI `{}` for 32-bit MIPS target", s))
                }
                s => sess.dcx().fatal(format!("invalid LLVM ABI `{}` for 64-bit 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
            // `unstable_target_features` is used here because "zca" is gated behind riscv_target_feature.
            if sess.unstable_target_features.contains(&sym::zca) {
                e_flags |= elf::EF_RISCV_RVC;
            }

            // Check if RVTSO is enabled
            // `unstable_target_features` is used here because "ztso" is gated behind riscv_target_feature.
            if sess.unstable_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 {
                "ilp32" | "lp64" => (),
                "ilp32f" | "lp64f" => e_flags |= elf::EF_RISCV_FLOAT_ABI_SINGLE,
                "ilp32d" | "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.
                "ilp32e" | "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 {
                "ilp32s" | "lp64s" => e_flags |= elf::EF_LARCH_ABI_SOFT_FLOAT,
                "ilp32f" | "lp64f" => e_flags |= elf::EF_LARCH_ABI_SINGLE_FLOAT,
                "ilp32d" | "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.abi, Abi::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.as_ref() {
                // 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.
                "elfv1" => EF_PPC64_ABI_ELF_V1,
                "elfv2" => EF_PPC64_ABI_ELF_V2,
                "" if sess.target.options.binary_format.to_object() == BinaryFormat::Elf => {
                    bug!("No ABI specified for this PPC64 ELF target");
                }
                // Fall back
                _ => EF_PPC64_ABI_UNKNOWN,
            }
        }
        _ => 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()
}
