//! 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
            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 {
                "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()
}
