Skip to content

Commit

Permalink
Auto merge of #127941 - GuillaumeGomez:rollup-s5eqz72, r=GuillaumeGomez
Browse files Browse the repository at this point in the history
Rollup of 5 pull requests

Successful merges:

 - #121533 (Handle .init_array link_section specially on wasm)
 - #123196 (Add Process support for UEFI)
 - #127621 (Rewrite and rename `issue-22131` and `issue-26006` `run-make` tests to rmake)
 - #127928 (Migrate `lto-smoke-c` and `link-path-order` `run-make` tests to rmake)
 - #127935 (Change `binary_asm_labels` to only fire on x86 and x86_64)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jul 19, 2024
2 parents 5affbb1 + fb751e0 commit 0cb871d
Show file tree
Hide file tree
Showing 26 changed files with 1,093 additions and 97 deletions.
10 changes: 8 additions & 2 deletions compiler/rustc_codegen_llvm/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -495,8 +495,14 @@ impl<'ll> CodegenCx<'ll, '_> {
}

// Wasm statics with custom link sections get special treatment as they
// go into custom sections of the wasm executable.
if self.tcx.sess.target.is_like_wasm {
// go into custom sections of the wasm executable. The exception to this
// is the `.init_array` section which are treated specially by the wasm linker.
if self.tcx.sess.target.is_like_wasm
&& attrs
.link_section
.map(|link_section| !link_section.as_str().starts_with(".init_array"))
.unwrap_or(true)
{
if let Some(section) = attrs.link_section {
let section = llvm::LLVMMDStringInContext2(
self.llcx,
Expand Down
35 changes: 28 additions & 7 deletions compiler/rustc_hir_analysis/src/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,21 +166,42 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) {
return;
}

// For the wasm32 target statics with `#[link_section]` are placed into custom
// sections of the final output file, but this isn't link custom sections of
// other executable formats. Namely we can only embed a list of bytes,
// nothing with provenance (pointers to anything else). If any provenance
// show up, reject it here.
// For the wasm32 target statics with `#[link_section]` other than `.init_array`
// are placed into custom sections of the final output file, but this isn't like
// custom sections of other executable formats. Namely we can only embed a list
// of bytes, nothing with provenance (pointers to anything else). If any
// provenance show up, reject it here.
// `#[link_section]` may contain arbitrary, or even undefined bytes, but it is
// the consumer's responsibility to ensure all bytes that have been read
// have defined values.
//
// The `.init_array` section is left to go through the normal custom section code path.
// When dealing with `.init_array` wasm-ld currently has several limitations. This manifests
// in workarounds in user-code.
//
// * The linker fails to merge multiple items in a crate into the .init_array section.
// To work around this, a single array can be used placing multiple items in the array.
// #[link_section = ".init_array"]
// static FOO: [unsafe extern "C" fn(); 2] = [ctor, ctor];
// * Even symbols marked used get gc'd from dependant crates unless at least one symbol
// in the crate is marked with an `#[export_name]`
//
// Once `.init_array` support in wasm-ld is complete, the user code workarounds should
// continue to work, but would no longer be necessary.

if let Ok(alloc) = tcx.eval_static_initializer(id.to_def_id())
&& alloc.inner().provenance().ptrs().len() != 0
{
let msg = "statics with a custom `#[link_section]` must be a \
if attrs
.link_section
.map(|link_section| !link_section.as_str().starts_with(".init_array"))
.unwrap()
{
let msg = "statics with a custom `#[link_section]` must be a \
simple list of bytes on the wasm target with no \
extra levels of indirection such as references";
tcx.dcx().span_err(tcx.def_span(id), msg);
tcx.dcx().span_err(tcx.def_span(id), msg);
}
}
}

Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_lint/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -403,8 +403,9 @@ lint_inner_macro_attribute_unstable = inner macro attributes are unstable
lint_invalid_asm_label_binary = avoid using labels containing only the digits `0` and `1` in inline assembly
.label = use a different label that doesn't start with `0` or `1`
.note = an LLVM bug makes these labels ambiguous with a binary literal number
.note = see <https://bugs.llvm.org/show_bug.cgi?id=36144> for more information
.help = start numbering with `2` instead
.note1 = an LLVM bug makes these labels ambiguous with a binary literal number on x86
.note2 = see <https://github.com/llvm/llvm-project/issues/99547> for more information
lint_invalid_asm_label_format_arg = avoid using named labels in inline assembly
.help = only local labels of the form `<number>:` should be used in inline asm
Expand Down
25 changes: 16 additions & 9 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{BytePos, InnerSpan, Span};
use rustc_target::abi::Abi;
use rustc_target::asm::InlineAsmArch;
use rustc_trait_selection::infer::{InferCtxtExt, TyCtxtInferExt};
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_trait_selection::traits::{self, misc::type_allowed_to_implement_copy};
Expand Down Expand Up @@ -2908,16 +2909,22 @@ impl<'tcx> LateLintPass<'tcx> for AsmLabels {
InvalidAsmLabel::FormatArg { missing_precise_span },
);
}
AsmLabelKind::Binary => {
// the binary asm issue only occurs when using intel syntax
if !options.contains(InlineAsmOptions::ATT_SYNTAX) {
cx.emit_span_lint(
BINARY_ASM_LABELS,
span,
InvalidAsmLabel::Binary { missing_precise_span, span },
)
}
// the binary asm issue only occurs when using intel syntax on x86 targets
AsmLabelKind::Binary
if !options.contains(InlineAsmOptions::ATT_SYNTAX)
&& matches!(
cx.tcx.sess.asm_arch,
Some(InlineAsmArch::X86 | InlineAsmArch::X86_64) | None
) =>
{
cx.emit_span_lint(
BINARY_ASM_LABELS,
span,
InvalidAsmLabel::Binary { missing_precise_span, span },
)
}
// No lint on anything other than x86
AsmLabelKind::Binary => (),
};
}
}
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2074,7 +2074,9 @@ pub enum InvalidAsmLabel {
missing_precise_span: bool,
},
#[diag(lint_invalid_asm_label_binary)]
#[note]
#[help]
#[note(lint_note1)]
#[note(lint_note2)]
Binary {
#[note(lint_invalid_asm_label_no_span)]
missing_precise_span: bool,
Expand Down
2 changes: 1 addition & 1 deletion library/std/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ hermit-abi = { version = "0.4.0", features = ['rustc-dep-of-std'], public = true
wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features = false }

[target.'cfg(target_os = "uefi")'.dependencies]
r-efi = { version = "4.2.0", features = ['rustc-dep-of-std'] }
r-efi = { version = "4.5.0", features = ['rustc-dep-of-std'] }
r-efi-alloc = { version = "1.0.0", features = ['rustc-dep-of-std'] }

[features]
Expand Down
1 change: 1 addition & 0 deletions library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@
#![feature(doc_masked)]
#![feature(doc_notable_trait)]
#![feature(dropck_eyepatch)]
#![feature(extended_varargs_abi_support)]
#![feature(f128)]
#![feature(f16)]
#![feature(if_let_guard)]
Expand Down
199 changes: 197 additions & 2 deletions library/std/src/sys/pal/uefi/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,21 @@
use r_efi::efi::{self, Guid};
use r_efi::protocols::{device_path, device_path_to_text};

use crate::ffi::OsString;
use crate::ffi::{OsStr, OsString};
use crate::io::{self, const_io_error};
use crate::mem::{size_of, MaybeUninit};
use crate::os::uefi::{self, env::boot_services, ffi::OsStringExt};
use crate::os::uefi::{self, env::boot_services, ffi::OsStrExt, ffi::OsStringExt};
use crate::ptr::NonNull;
use crate::slice;
use crate::sync::atomic::{AtomicPtr, Ordering};
use crate::sys_common::wstr::WStrUnits;

type BootInstallMultipleProtocolInterfaces =
unsafe extern "efiapi" fn(_: *mut r_efi::efi::Handle, _: ...) -> r_efi::efi::Status;

type BootUninstallMultipleProtocolInterfaces =
unsafe extern "efiapi" fn(_: r_efi::efi::Handle, _: ...) -> r_efi::efi::Status;

const BOOT_SERVICES_UNAVAILABLE: io::Error =
const_io_error!(io::ErrorKind::Other, "Boot Services are no longer available");

Expand Down Expand Up @@ -221,3 +227,192 @@ pub(crate) fn runtime_services() -> Option<NonNull<r_efi::efi::RuntimeServices>>
let runtime_services = unsafe { (*system_table.as_ptr()).runtime_services };
NonNull::new(runtime_services)
}

pub(crate) struct DevicePath(NonNull<r_efi::protocols::device_path::Protocol>);

impl DevicePath {
pub(crate) fn from_text(p: &OsStr) -> io::Result<Self> {
fn inner(
p: &OsStr,
protocol: NonNull<r_efi::protocols::device_path_from_text::Protocol>,
) -> io::Result<DevicePath> {
let path_vec = p.encode_wide().chain(Some(0)).collect::<Vec<u16>>();
if path_vec[..path_vec.len() - 1].contains(&0) {
return Err(const_io_error!(
io::ErrorKind::InvalidInput,
"strings passed to UEFI cannot contain NULs",
));
}

let path =
unsafe { ((*protocol.as_ptr()).convert_text_to_device_path)(path_vec.as_ptr()) };

NonNull::new(path).map(DevicePath).ok_or_else(|| {
const_io_error!(io::ErrorKind::InvalidFilename, "Invalid Device Path")
})
}

static LAST_VALID_HANDLE: AtomicPtr<crate::ffi::c_void> =
AtomicPtr::new(crate::ptr::null_mut());

if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) {
if let Ok(protocol) = open_protocol::<r_efi::protocols::device_path_from_text::Protocol>(
handle,
r_efi::protocols::device_path_from_text::PROTOCOL_GUID,
) {
return inner(p, protocol);
}
}

let handles = locate_handles(r_efi::protocols::device_path_from_text::PROTOCOL_GUID)?;
for handle in handles {
if let Ok(protocol) = open_protocol::<r_efi::protocols::device_path_from_text::Protocol>(
handle,
r_efi::protocols::device_path_from_text::PROTOCOL_GUID,
) {
LAST_VALID_HANDLE.store(handle.as_ptr(), Ordering::Release);
return inner(p, protocol);
}
}

io::Result::Err(const_io_error!(
io::ErrorKind::NotFound,
"DevicePathFromText Protocol not found"
))
}

pub(crate) fn as_ptr(&self) -> *mut r_efi::protocols::device_path::Protocol {
self.0.as_ptr()
}
}

impl Drop for DevicePath {
fn drop(&mut self) {
if let Some(bt) = boot_services() {
let bt: NonNull<r_efi::efi::BootServices> = bt.cast();
unsafe {
((*bt.as_ptr()).free_pool)(self.0.as_ptr() as *mut crate::ffi::c_void);
}
}
}
}

pub(crate) struct OwnedProtocol<T> {
guid: r_efi::efi::Guid,
handle: NonNull<crate::ffi::c_void>,
protocol: *mut T,
}

impl<T> OwnedProtocol<T> {
// FIXME: Consider using unsafe trait for matching protocol with guid
pub(crate) unsafe fn create(protocol: T, mut guid: r_efi::efi::Guid) -> io::Result<Self> {
let bt: NonNull<r_efi::efi::BootServices> =
boot_services().ok_or(BOOT_SERVICES_UNAVAILABLE)?.cast();
let protocol: *mut T = Box::into_raw(Box::new(protocol));
let mut handle: r_efi::efi::Handle = crate::ptr::null_mut();

// FIXME: Move into r-efi once extended_varargs_abi_support is stablized
let func: BootInstallMultipleProtocolInterfaces =
unsafe { crate::mem::transmute((*bt.as_ptr()).install_multiple_protocol_interfaces) };

let r = unsafe {
func(
&mut handle,
&mut guid as *mut _ as *mut crate::ffi::c_void,
protocol as *mut crate::ffi::c_void,
crate::ptr::null_mut() as *mut crate::ffi::c_void,
)
};

if r.is_error() {
drop(Box::from_raw(protocol));
return Err(crate::io::Error::from_raw_os_error(r.as_usize()));
};

let handle = NonNull::new(handle)
.ok_or(io::const_io_error!(io::ErrorKind::Uncategorized, "found null handle"))?;

Ok(Self { guid, handle, protocol })
}

pub(crate) fn handle(&self) -> NonNull<crate::ffi::c_void> {
self.handle
}
}

impl<T> Drop for OwnedProtocol<T> {
fn drop(&mut self) {
// Do not deallocate a runtime protocol
if let Some(bt) = boot_services() {
let bt: NonNull<r_efi::efi::BootServices> = bt.cast();
// FIXME: Move into r-efi once extended_varargs_abi_support is stablized
let func: BootUninstallMultipleProtocolInterfaces = unsafe {
crate::mem::transmute((*bt.as_ptr()).uninstall_multiple_protocol_interfaces)
};
let status = unsafe {
func(
self.handle.as_ptr(),
&mut self.guid as *mut _ as *mut crate::ffi::c_void,
self.protocol as *mut crate::ffi::c_void,
crate::ptr::null_mut() as *mut crate::ffi::c_void,
)
};

// Leak the protocol in case uninstall fails
if status == r_efi::efi::Status::SUCCESS {
let _ = unsafe { Box::from_raw(self.protocol) };
}
}
}
}

impl<T> AsRef<T> for OwnedProtocol<T> {
fn as_ref(&self) -> &T {
unsafe { self.protocol.as_ref().unwrap() }
}
}

pub(crate) struct OwnedTable<T> {
layout: crate::alloc::Layout,
ptr: *mut T,
}

impl<T> OwnedTable<T> {
pub(crate) fn from_table_header(hdr: &r_efi::efi::TableHeader) -> Self {
let header_size = hdr.header_size as usize;
let layout = crate::alloc::Layout::from_size_align(header_size, 8).unwrap();
let ptr = unsafe { crate::alloc::alloc(layout) as *mut T };
Self { layout, ptr }
}

pub(crate) const fn as_ptr(&self) -> *const T {
self.ptr
}

pub(crate) const fn as_mut_ptr(&self) -> *mut T {
self.ptr
}
}

impl OwnedTable<r_efi::efi::SystemTable> {
pub(crate) fn from_table(tbl: *const r_efi::efi::SystemTable) -> Self {
let hdr = unsafe { (*tbl).hdr };

let owned_tbl = Self::from_table_header(&hdr);
unsafe {
crate::ptr::copy_nonoverlapping(
tbl as *const u8,
owned_tbl.as_mut_ptr() as *mut u8,
hdr.header_size as usize,
)
};

owned_tbl
}
}

impl<T> Drop for OwnedTable<T> {
fn drop(&mut self) {
unsafe { crate::alloc::dealloc(self.ptr as *mut u8, self.layout) };
}
}
1 change: 0 additions & 1 deletion library/std/src/sys/pal/uefi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ pub mod net;
pub mod os;
#[path = "../unsupported/pipe.rs"]
pub mod pipe;
#[path = "../unsupported/process.rs"]
pub mod process;
pub mod stdio;
pub mod thread;
Expand Down
Loading

0 comments on commit 0cb871d

Please sign in to comment.