Skip to content

Commit

Permalink
dist: Ensure UEFI rlibs are all COFF
Browse files Browse the repository at this point in the history
If clang isn't the C compiler used for the UEFI targets, or if the wrong
`--target` is passed to clang, we will get ELF objects in some
rlibs. This will cause problems at link time when trying to compile a
UEFI program that uses any of those objects. Add a check to the dist
step for UEFI targets that reads each rlib with the `object` crate and
fails with an error if any non-COFF objects are found.
  • Loading branch information
nicholasbishop committed Nov 20, 2022
1 parent 01a2a54 commit 6054608
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/bootstrap/Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ dependencies = [
"hex",
"ignore",
"libc",
"object",
"once_cell",
"opener",
"pretty_assertions",
Expand Down Expand Up @@ -400,6 +401,15 @@ dependencies = [
"libc",
]

[[package]]
name = "object"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
dependencies = [
"memchr",
]

[[package]]
name = "once_cell"
version = "1.12.0"
Expand Down
1 change: 1 addition & 0 deletions src/bootstrap/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ getopts = "0.2.19"
cc = "1.0.69"
libc = "0.2"
hex = "0.4"
object = { version = "0.29.0", default-features = false, features = ["archive", "coff", "read_core", "unaligned"] }
serde = { version = "1.0.8", features = ["derive"] }
serde_json = "1.0.2"
sha2 = "0.10"
Expand Down
38 changes: 38 additions & 0 deletions src/bootstrap/dist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@

use std::collections::HashSet;
use std::env;
use std::ffi::OsStr;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;

use object::read::archive::ArchiveFile;
use object::BinaryFormat;

use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
use crate::cache::{Interned, INTERNER};
use crate::channel;
Expand Down Expand Up @@ -555,6 +559,39 @@ fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool {
}
}

/// Check that all objects in rlibs for UEFI targets are COFF. This
/// ensures that the C compiler isn't producing ELF objects, which would
/// not link correctly with the COFF objects.
fn verify_uefi_rlib_format(builder: &Builder<'_>, target: TargetSelection, stamp: &Path) {
if !target.ends_with("-uefi") {
return;
}

for (path, _) in builder.read_stamp_file(stamp) {
if path.extension() != Some(OsStr::new("rlib")) {
continue;
}

let data = t!(fs::read(&path));
let data = data.as_slice();
let archive = t!(ArchiveFile::parse(data));
for member in archive.members() {
let member = t!(member);
let member_data = t!(member.data(data));

let is_coff = match object::File::parse(member_data) {
Ok(member_file) => member_file.format() == BinaryFormat::Coff,
Err(_) => false,
};

if !is_coff {
let member_name = String::from_utf8_lossy(member.name());
panic!("member {} in {} is not COFF", member_name, path.display());
}
}
}
}

/// Copy stamped files into an image's `target/lib` directory.
fn copy_target_libs(builder: &Builder<'_>, target: TargetSelection, image: &Path, stamp: &Path) {
let dst = image.join("lib/rustlib").join(target.triple).join("lib");
Expand Down Expand Up @@ -610,6 +647,7 @@ impl Step for Std {

let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
let stamp = compile::libstd_stamp(builder, compiler_to_use, target);
verify_uefi_rlib_format(builder, target, &stamp);
copy_target_libs(builder, target, &tarball.image_dir(), &stamp);

Some(tarball.generate())
Expand Down

0 comments on commit 6054608

Please sign in to comment.