1
Fork 0

Auto merge of #132362 - mustartt:aix-dylib-detection, r=jieyouxu

[AIX] change system dynamic library format

Historically on AIX, almost all dynamic libraries are distributed in `.a` Big Archive Format which can consists of both static and shared objects in the same archive (e.g. `libc++abi.a(libc++abi.so.1)`). During the initial porting process, the dynamic libraries are kept as `.a` to simplify the migration, but semantically having an XCOFF object under the archive extension is wrong. For crate type `cdylib` we want to be able to distribute the libraries as archives as well.

We are migrating to archives with the following format:
```
$ ar -t lib<name>.a
lib<name>.so
```
where each archive contains a single member that is a shared XCOFF object that can be loaded.
This commit is contained in:
bors 2024-11-21 21:36:47 +00:00
commit 5d3c6ee9b3
10 changed files with 127 additions and 22 deletions

View file

@ -777,6 +777,16 @@ fn link_natively(
info!("preparing {:?} to {:?}", crate_type, out_filename);
let (linker_path, flavor) = linker_and_flavor(sess);
let self_contained_components = self_contained_components(sess, crate_type);
// On AIX, we ship all libraries as .a big_af archive
// the expected format is lib<name>.a(libname.so) for the actual
// dynamic library. So we link to a temporary .so file to be archived
// at the final out_filename location
let should_archive = crate_type != CrateType::Executable && sess.target.is_like_aix;
let archive_member =
should_archive.then(|| tmpdir.join(out_filename.file_name().unwrap()).with_extension("so"));
let temp_filename = archive_member.as_deref().unwrap_or(out_filename);
let mut cmd = linker_with_args(
&linker_path,
flavor,
@ -784,7 +794,7 @@ fn link_natively(
archive_builder_builder,
crate_type,
tmpdir,
out_filename,
temp_filename,
codegen_results,
self_contained_components,
)?;
@ -1158,6 +1168,12 @@ fn link_natively(
}
}
if should_archive {
let mut ab = archive_builder_builder.new_archive_builder(sess);
ab.add_file(temp_filename);
ab.build(out_filename);
}
Ok(())
}

View file

@ -5,6 +5,7 @@ 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,
@ -21,6 +22,7 @@ use rustc_middle::bug;
use rustc_session::Session;
use rustc_span::sym;
use rustc_target::spec::{RelocModel, Target, ef_avr_arch};
use tracing::debug;
use super::apple;
@ -53,6 +55,7 @@ fn load_metadata_with(
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))?;
@ -77,8 +80,26 @@ impl MetadataLoader for DefaultMetadataLoader {
}
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| get_metadata_xcoff(path, data))
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"))
}