diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index 7beee7e341b90..26a6b7c416955 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -8,9 +8,9 @@ use rustc_span::edition::Edition::Edition2024; use super::prelude::*; use crate::attributes::AttributeSafety; use crate::session_diagnostics::{ - EmptyExportName, NakedFunctionIncompatibleAttribute, NullOnExport, NullOnObjcClass, - NullOnObjcSelector, ObjcClassExpectedStringLiteral, ObjcSelectorExpectedStringLiteral, - SanitizeInvalidStatic, + EmptyExportName, EmptySection, NakedFunctionIncompatibleAttribute, NullOnExport, + NullOnObjcClass, NullOnObjcSelector, NullOnSection, ObjcClassExpectedStringLiteral, + ObjcSelectorExpectedStringLiteral, SanitizeInvalidStatic, }; use crate::target_checking::Policy::AllowSilent; @@ -781,7 +781,8 @@ pub(crate) struct PatchableFunctionEntryParser; impl SingleAttributeParser for PatchableFunctionEntryParser { const PATH: &[Symbol] = &[sym::patchable_function_entry]; const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]); - const TEMPLATE: AttributeTemplate = template!(List: &["prefix_nops = m, entry_nops = n"]); + const TEMPLATE: AttributeTemplate = + template!(List: &["prefix_nops = m, entry_nops = n, section = \"section\""]); const STABILITY: AttributeStability = unstable!(patchable_function_entry); fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { @@ -789,74 +790,85 @@ impl SingleAttributeParser for PatchableFunctionEntryParser { let mut prefix = None; let mut entry = None; + let mut section = None; if meta_item_list.len() == 0 { cx.adcx().expected_at_least_one_argument(meta_item_list.span); return None; } - let mut errored = false; - for item in meta_item_list.mixed() { let Some((ident, value)) = cx.expect_name_value(item, item.span(), None) else { - continue; + return None; }; let attrib_to_write = match ident.name { sym::prefix_nops => { // Duplicate prefixes are not allowed if prefix.is_some() { - errored = true; cx.adcx().duplicate_key(ident.span, sym::prefix_nops); - continue; + return None; } &mut prefix } sym::entry_nops => { // Duplicate entries are not allowed if entry.is_some() { - errored = true; cx.adcx().duplicate_key(ident.span, sym::entry_nops); - continue; + return None; } &mut entry } + sym::section => { + // Duplicate entries are not allowed + if section.is_some() { + cx.adcx().duplicate_key(ident.span, sym::section); + return None; + } + // Only a string type value is allowed. + let Some(value_str) = value.value_as_str() else { + cx.adcx().expect_string_literal(value); + return None; + }; + // The section name does not allow null characters. + if value_str.as_str().contains('\0') { + cx.emit_err(NullOnSection { span: value.value_span }); + } + // The section name is not allowed to be empty, LLVM does + // not allow them. + if value_str.is_empty() { + cx.emit_err(EmptySection { span: value.value_span }); + } + section = Some(value_str); + // Integer parsing is not needed, process next item. + continue; + } _ => { - errored = true; cx.adcx().expected_specific_argument( ident.span, &[sym::prefix_nops, sym::entry_nops], ); - continue; + return None; } }; let rustc_ast::LitKind::Int(val, _) = value.value_as_lit().kind else { - errored = true; cx.adcx().expected_integer_literal(value.value_span); - continue; + return None; }; let Ok(val) = val.get().try_into() else { - errored = true; cx.adcx().expected_integer_literal_in_range( value.value_span, u8::MIN as isize, u8::MAX as isize, ); - continue; + return None; }; *attrib_to_write = Some(val); } - if errored { - None - } else { - Some(AttributeKind::PatchableFunctionEntry { - prefix: prefix.unwrap_or(0), - entry: entry.unwrap_or(0), - }) - } + Some(AttributeKind::PatchableFunctionEntry { prefix, entry, section }) } } diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index fef6f7d9e5503..2df483dc5bb84 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -265,6 +265,13 @@ pub(crate) struct EmptyExportName { pub span: Span, } +#[derive(Diagnostic)] +#[diag("`section` may not be empty")] +pub(crate) struct EmptySection { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag("`export_name` may not contain null characters", code = E0648)] pub(crate) struct NullOnExport { @@ -300,6 +307,13 @@ pub(crate) struct NullOnObjcSelector { pub span: Span, } +#[derive(Diagnostic)] +#[diag("`section` may not contain null characters", code = E0648)] +pub(crate) struct NullOnSection { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag("`objc::class!` expected a string literal")] pub(crate) struct ObjcClassExpectedStringLiteral { diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index fe36a9865485d..20e712174e0e9 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -86,11 +86,26 @@ fn patchable_function_entry_attrs<'ll>( attr: Option, ) -> SmallVec<[&'ll Attribute; 2]> { let mut attrs = SmallVec::new(); - let patchable_spec = attr.unwrap_or_else(|| { - PatchableFunctionEntry::from_config(sess.opts.unstable_opts.patchable_function_entry) - }); - let entry = patchable_spec.entry(); - let prefix = patchable_spec.prefix(); + + let mut entry = sess.opts.unstable_opts.patchable_function_entry.entry(); + let mut prefix = sess.opts.unstable_opts.patchable_function_entry.prefix(); + let mut section = sess.opts.unstable_opts.patchable_function_entry.section(); + let section_sym; + + // Apply attribute specified overrides, if any. + if let Some(patchable_spec) = attr { + if let Some(sym) = patchable_spec.section() { + section_sym = sym; + section = Some(section_sym.as_str()); + } + // Override the nop counts if either is present. If only one is present, the + // other count is implied to be 0. + if patchable_spec.entry().is_some() || patchable_spec.prefix().is_some() { + entry = patchable_spec.entry().unwrap_or(0); + prefix = patchable_spec.prefix().unwrap_or(0); + } + } + if entry > 0 { attrs.push(llvm::CreateAttrStringValue( cx.llcx, @@ -105,6 +120,13 @@ fn patchable_function_entry_attrs<'ll>( &format!("{}", prefix), )); } + if let Some(section) = section { + attrs.push(llvm::CreateAttrStringValue( + cx.llcx, + "patchable-function-entry-section", + section, + )); + } attrs } diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 84661f5160b14..3461edc9d18aa 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -14,7 +14,6 @@ use rustc_data_structures::base_n::{ALPHANUMERIC_ONLY, ToBaseN}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; -use rustc_middle::middle::codegen_fn_attrs::PatchableFunctionEntry; use rustc_middle::mono::CodegenUnit; use rustc_middle::ty::layout::{ FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTypingEnv, LayoutError, LayoutOfHelpers, @@ -343,14 +342,13 @@ pub(crate) unsafe fn create_module<'ll>( // Add "kcfi-offset" module flag with -Z patchable-function-entry (See // https://reviews.llvm.org/D141172). - let pfe = - PatchableFunctionEntry::from_config(sess.opts.unstable_opts.patchable_function_entry); - if pfe.prefix() > 0 { + let patchable_prefix_nops = sess.opts.unstable_opts.patchable_function_entry.prefix(); + if patchable_prefix_nops > 0 { llvm::add_module_flag_u32( llmod, llvm::ModuleFlagMergeBehavior::Override, "kcfi-offset", - pfe.prefix().into(), + patchable_prefix_nops.into(), ); } diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 4d271447746c1..46bb1182c298c 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -290,9 +290,11 @@ fn process_builtin_attrs( AttributeKind::RustcOffloadKernel => { codegen_fn_attrs.flags |= CodegenFnAttrFlags::OFFLOAD_KERNEL } - AttributeKind::PatchableFunctionEntry { prefix, entry } => { + AttributeKind::PatchableFunctionEntry { prefix, entry, section } => { codegen_fn_attrs.patchable_function_entry = - Some(PatchableFunctionEntry::from_prefix_and_entry(*prefix, *entry)); + Some(PatchableFunctionEntry::from_prefix_entry_and_section( + *prefix, *entry, *section, + )); } AttributeKind::InstrumentFn(instrument_fn) => { codegen_fn_attrs.instrument_fn = match instrument_fn { diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 7c125c3a8983e..5aa2253672504 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1224,8 +1224,9 @@ pub enum AttributeKind { /// Represents `#[patchable_function_entry]` PatchableFunctionEntry { - prefix: u8, - entry: u8, + prefix: Option, + entry: Option, + section: Option, }, /// Represents `#[path]` diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 5933d0fd4b356..a3264d3cc3311 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -866,7 +866,7 @@ fn test_unstable_options_tracking_hash() { tracked!(panic_in_drop, PanicStrategy::Abort); tracked!( patchable_function_entry, - PatchableFunctionEntry::from_total_and_prefix_nops(10, 5) + PatchableFunctionEntry::from_parts(10, 5, None) .expect("total must be greater than or equal to prefix") ); tracked!(plt, Some(true)); diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index 713c6597c1966..b6ae4a98a34e3 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -114,7 +114,7 @@ pub struct CodegenFnAttrs { // FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity pub alignment: Option, /// The `#[patchable_function_entry(...)]` attribute. Indicates how many nops should be around - /// the function entry. + /// the function entry, or override default section to record entry location. pub patchable_function_entry: Option, /// The `#[rustc_objc_class = "..."]` attribute. pub objc_class: Option, @@ -162,24 +162,33 @@ pub struct TargetFeature { #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, StableHash)] pub struct PatchableFunctionEntry { /// Nops to prepend to the function - prefix: u8, + prefix: Option, /// Nops after entry, but before body - entry: u8, + entry: Option, + /// Optional, specific section to record entry location in + section: Option, } impl PatchableFunctionEntry { - pub fn from_config(config: rustc_session::config::PatchableFunctionEntry) -> Self { - Self { prefix: config.prefix(), entry: config.entry() } + pub fn from_prefix_entry_and_section( + prefix: Option, + entry: Option, + section: Option, + ) -> Self { + Self { prefix, entry, section } } pub fn from_prefix_and_entry(prefix: u8, entry: u8) -> Self { - Self { prefix, entry } + Self { prefix: Some(prefix), entry: Some(entry), section: None } } - pub fn prefix(&self) -> u8 { + pub fn prefix(&self) -> Option { self.prefix } - pub fn entry(&self) -> u8 { + pub fn entry(&self) -> Option { self.entry } + pub fn section(&self) -> Option { + self.section + } } #[derive(Clone, Copy, PartialEq, Eq, TyEncodable, TyDecodable, StableHash)] diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index c7da2d9a1fc38..4492cdf2d2f8a 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -3342,23 +3342,29 @@ impl DumpMonoStatsFormat { /// `-Z patchable-function-entry` representation - how many nops to put before and after function /// entry. -#[derive(Clone, Copy, PartialEq, Hash, Debug, Default)] +#[derive(Clone, PartialEq, Hash, Debug, Default)] pub struct PatchableFunctionEntry { /// Nops before the entry prefix: u8, /// Nops after the entry entry: u8, + /// An optional section name to record the entry location + section: Option, } impl PatchableFunctionEntry { - pub fn from_total_and_prefix_nops( + pub fn from_parts( total_nops: u8, prefix_nops: u8, + section: Option, ) -> Option { if total_nops < prefix_nops { None + // Section name cannot contain null characters. + } else if section.as_ref().map(|x| x.contains('\0') || x.is_empty()).unwrap_or(false) { + None } else { - Some(Self { prefix: prefix_nops, entry: total_nops - prefix_nops }) + Some(Self { prefix: prefix_nops, entry: total_nops - prefix_nops, section }) } } pub fn prefix(&self) -> u8 { @@ -3367,6 +3373,9 @@ impl PatchableFunctionEntry { pub fn entry(&self) -> u8 { self.entry } + pub fn section(&self) -> Option<&str> { + self.section.as_ref().map(|x| x.as_str()) + } } /// `-Zpolonius` values, enabling the borrow checker polonius analysis, and which version: legacy, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index efc8a70f4feb2..b7668bd47d8ec 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -784,7 +784,7 @@ mod desc { pub(crate) const parse_passes: &str = "a space-separated list of passes, or `all`"; pub(crate) const parse_panic_strategy: &str = "either `unwind`, `abort`, or `immediate-abort`"; pub(crate) const parse_on_broken_pipe: &str = "either `kill`, `error`, or `inherit`"; - pub(crate) const parse_patchable_function_entry: &str = "either two comma separated integers (total_nops,prefix_nops), with prefix_nops <= total_nops, or one integer (total_nops)"; + pub(crate) const parse_patchable_function_entry: &str = "a comma separated list of (prefix_nops,total_nops,section_name), (prefix_nops,total_nops), or (total_nops). Where prefix_nops <= total_nops where 0 < total_nops <= 255 and prefix_nops <= total_nops"; pub(crate) const parse_opt_panic_strategy: &str = parse_panic_strategy; pub(crate) const parse_relro_level: &str = "one of: `full`, `partial`, or `off`"; pub(crate) const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `dataflow`, `hwaddress`, `kcfi`, `kernel-address`, `kernel-hwaddress`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, `thread`, or 'realtime'"; @@ -1206,20 +1206,24 @@ pub mod parse { ) -> bool { let mut total_nops = 0; let mut prefix_nops = 0; + let mut section = None; if !parse_number(&mut total_nops, v) { - let parts = v.and_then(|v| v.split_once(',')).unzip(); - if !parse_number(&mut total_nops, parts.0) { + let parts: Vec<_> = v.unwrap_or("").split(',').collect(); + if parts.len() < 2 || parts.len() > 3 { return false; } - if !parse_number(&mut prefix_nops, parts.1) { + + if !parse_number(&mut total_nops, Some(parts[0])) { + return false; + } + if !parse_number(&mut prefix_nops, Some(parts[1])) { return false; } + section = parts.get(2).map(|x| x.to_string()); } - if let Some(pfe) = - PatchableFunctionEntry::from_total_and_prefix_nops(total_nops, prefix_nops) - { + if let Some(pfe) = PatchableFunctionEntry::from_parts(total_nops, prefix_nops, section) { *slot = pfe; return true; } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 827e33dcd6632..35c4f7afde541 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1868,6 +1868,7 @@ symbols! { saturating_sub, sdylib, search_unbox, + section, select_unpredictable, self_in_typedefs, self_struct_ctor, diff --git a/src/doc/unstable-book/src/compiler-flags/patchable-function-entry.md b/src/doc/unstable-book/src/compiler-flags/patchable-function-entry.md index 4a9bf47a29011..80f0e54907872 100644 --- a/src/doc/unstable-book/src/compiler-flags/patchable-function-entry.md +++ b/src/doc/unstable-book/src/compiler-flags/patchable-function-entry.md @@ -2,10 +2,13 @@ -------------------- -The `-Z patchable-function-entry=total_nops,prefix_nops` or `-Z patchable-function-entry=total_nops` +The `-Z patchable-function-entry=total_nops,prefix_nops,record_section`, + `-Z patchable-function-entry=total_nops,prefix_nops`, or + `-Z patchable-function-entry=total_nops` compiler flag enables nop padding of function entries with 'total_nops' nops, with -an offset for the entry of the function at 'prefix_nops' nops. In the second form, -'prefix_nops' defaults to 0. +an offset for the entry of the function at 'prefix_nops' nops. In the third form, +'prefix_nops' defaults to 0. record\_section can specify a specific linker section +to place entry record in, the default is `__patchable_function_entries`. As an illustrative example, `-Z patchable-function-entry=3,2` would produce: diff --git a/tests/codegen-llvm/patchable-function-entry/patchable-function-entry-both-flags.rs b/tests/codegen-llvm/patchable-function-entry/patchable-function-entry-both-flags.rs index 72204c78a4906..45aa46d24fe94 100644 --- a/tests/codegen-llvm/patchable-function-entry/patchable-function-entry-both-flags.rs +++ b/tests/codegen-llvm/patchable-function-entry/patchable-function-entry-both-flags.rs @@ -39,6 +39,26 @@ pub fn fun5() {} #[patchable_function_entry(prefix_nops = 4)] pub fn fun6() {} +// The attribute should override patchable-function-prefix to 4 +// and patchable-function-entry to the default of 0, clearing it entirely, +// while setting patchable-function-entry-section. +#[no_mangle] +#[patchable_function_entry(prefix_nops = 4, section = "foo")] +pub fn fun7() {} + +// The attribute should override patchable-function-entry-section, +// while passing through the commandline options. +#[no_mangle] +#[patchable_function_entry(section = "bar")] +pub fn fun8() {} + +// The attribute should override patchable-function-entry to 5 +// and patchable-function-prefix to the default of 0, clearing it entirely, +// while setting patchable-function-entry-section. +#[no_mangle] +#[patchable_function_entry(entry_nops = 5, section = "baz")] +pub fn fun9() {} + // CHECK: @fun0() unnamed_addr #0 // CHECK: @fun1() unnamed_addr #1 // CHECK: @fun2() unnamed_addr #2 @@ -46,6 +66,9 @@ pub fn fun6() {} // CHECK: @fun4() unnamed_addr #4 // CHECK: @fun5() unnamed_addr #5 // CHECK: @fun6() unnamed_addr #6 +// CHECK: @fun7() unnamed_addr #7 +// CHECK: @fun8() unnamed_addr #8 +// CHECK: @fun9() unnamed_addr #9 // CHECK: attributes #0 = { {{.*}}"patchable-function-entry"="5"{{.*}}"patchable-function-prefix"="10" {{.*}} } // CHECK: attributes #1 = { {{.*}}"patchable-function-entry"="2"{{.*}}"patchable-function-prefix"="1" {{.*}} } @@ -62,3 +85,12 @@ pub fn fun6() {} // CHECK: attributes #6 = { {{.*}}"patchable-function-prefix"="4"{{.*}} } // CHECK-NOT: attributes #6 = { {{.*}}patchable-function-entry{{.*}} } +// +// CHECK: attributes #7 = { {{.*}}"patchable-function-entry-section"="foo"{{.*}}"patchable-function-prefix"="4" {{.*}} } +// CHECK-NOT: attributes #7 = { {{.*}}"patchable-function-entry"{{.*}} } +// +// CHECK: attributes #8 = { {{.*}}"patchable-function-entry-section"="bar"{{.*}} } +// CHECK-NOT: attributes #8 = { {{.*}}"patchable-function-entry"{{.*}} } +// +// CHECK: attributes #9 = { {{.*}}"patchable-function-entry"="5"{{.*}}"patchable-function-entry-section"="baz" {{.*}} } +// CHECK-NOT: attributes #9 = { {{.*}}"patchable-function-prefix{{.*}} } diff --git a/tests/codegen-llvm/patchable-function-entry/patchable-function-entry-section.rs b/tests/codegen-llvm/patchable-function-entry/patchable-function-entry-section.rs new file mode 100644 index 0000000000000..9ffff5ca7537c --- /dev/null +++ b/tests/codegen-llvm/patchable-function-entry/patchable-function-entry-section.rs @@ -0,0 +1,20 @@ +//@ compile-flags: -Z patchable-function-entry=15,10,default_foo_section +// + +#![feature(patchable_function_entry)] +#![crate_type = "lib"] + +// This should have the default, as set by the compile flags +#[no_mangle] +pub fn fun0() {} + +// This should override the default section name +#[no_mangle] +#[patchable_function_entry(section = "bar_section")] +pub fn fun1() {} + +// CHECK: @fun0() unnamed_addr #0 +// CHECK: @fun1() unnamed_addr #1 + +// CHECK: attributes #0 = { {{.*}}"patchable-function-entry"="5"{{.*}}"patchable-function-entry-section"="default_foo_section"{{.*}}"patchable-function-prefix"="10" {{.*}} } +// CHECK: attributes #1 = { {{.*}}"patchable-function-entry"="5"{{.*}}"patchable-function-entry-section"="bar_section"{{.*}}"patchable-function-prefix"="10" {{.*}} } diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index 7d8bd3700d4bb..96012d8df936b 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -550,8 +550,8 @@ LL | #[patchable_function_entry] | help: must be of the form | -LL | #[patchable_function_entry(prefix_nops = m, entry_nops = n)] - | +++++++++++++++++++++++++++++++++ +LL | #[patchable_function_entry(prefix_nops = m, entry_nops = n, section = "section")] + | ++++++++++++++++++++++++++++++++++++++++++++++++++++++ error[E0565]: malformed `coroutine` attribute input --> $DIR/malformed-attrs.rs:118:5 diff --git a/tests/ui/patchable-function-entry/patchable-function-entry-attribute.rs b/tests/ui/patchable-function-entry/patchable-function-entry-attribute.rs index 5cbeccf1b0e4f..1223c0c5b05f9 100644 --- a/tests/ui/patchable-function-entry/patchable-function-entry-attribute.rs +++ b/tests/ui/patchable-function-entry/patchable-function-entry-attribute.rs @@ -24,3 +24,19 @@ pub fn no_parameters_given() {} #[patchable_function_entry(prefix_nops = 255, prefix_nops = 255)] //~^ ERROR malformed pub fn duplicate_parameter() {} + +#[patchable_function_entry(section = 255)] +//~^ ERROR malformed +pub fn invalid_section_parameter() {} + +#[patchable_function_entry(section = "foo", section = "bar")] +//~^ ERROR malformed +pub fn duplicate_section_parameter() {} + +#[patchable_function_entry(section = "fo\0o")] +//~^ ERROR null characters +pub fn nul_in_section_parameter() {} + +#[patchable_function_entry(section = "")] +//~^ ERROR empty +pub fn empty_section_parameter() {} diff --git a/tests/ui/patchable-function-entry/patchable-function-entry-attribute.stderr b/tests/ui/patchable-function-entry/patchable-function-entry-attribute.stderr index 6c32a76834c69..c3f09ff12384a 100644 --- a/tests/ui/patchable-function-entry/patchable-function-entry-attribute.stderr +++ b/tests/ui/patchable-function-entry/patchable-function-entry-attribute.stderr @@ -9,7 +9,7 @@ LL | #[patchable_function_entry(prefix_nops = 256, entry_nops = 0)] help: must be of the form | LL - #[patchable_function_entry(prefix_nops = 256, entry_nops = 0)] -LL + #[patchable_function_entry(prefix_nops = m, entry_nops = n)] +LL + #[patchable_function_entry(prefix_nops = m, entry_nops = n, section = "section")] | error[E0539]: malformed `patchable_function_entry` attribute input @@ -23,7 +23,7 @@ LL | #[patchable_function_entry(prefix_nops = "stringvalue", entry_nops = 0)] help: must be of the form | LL - #[patchable_function_entry(prefix_nops = "stringvalue", entry_nops = 0)] -LL + #[patchable_function_entry(prefix_nops = m, entry_nops = n)] +LL + #[patchable_function_entry(prefix_nops = m, entry_nops = n, section = "section")] | error[E0539]: malformed `patchable_function_entry` attribute input @@ -34,8 +34,8 @@ LL | #[patchable_function_entry] | help: must be of the form | -LL | #[patchable_function_entry(prefix_nops = m, entry_nops = n)] - | +++++++++++++++++++++++++++++++++ +LL | #[patchable_function_entry(prefix_nops = m, entry_nops = n, section = "section")] + | ++++++++++++++++++++++++++++++++++++++++++++++++++++++ error[E0539]: malformed `patchable_function_entry` attribute input --> $DIR/patchable-function-entry-attribute.rs:16:1 @@ -48,7 +48,7 @@ LL | #[patchable_function_entry(prefix_nops = 10, something = 0)] help: must be of the form | LL - #[patchable_function_entry(prefix_nops = 10, something = 0)] -LL + #[patchable_function_entry(prefix_nops = m, entry_nops = n)] +LL + #[patchable_function_entry(prefix_nops = m, entry_nops = n, section = "section")] | error[E0539]: malformed `patchable_function_entry` attribute input @@ -61,8 +61,8 @@ LL | #[patchable_function_entry()] | help: must be of the form | -LL | #[patchable_function_entry(prefix_nops = m, entry_nops = n)] - | +++++++++++++++++++++++++++++++ +LL | #[patchable_function_entry(prefix_nops = m, entry_nops = n, section = "section")] + | ++++++++++++++++++++++++++++++++++++++++++++++++++++ error[E0538]: malformed `patchable_function_entry` attribute input --> $DIR/patchable-function-entry-attribute.rs:24:1 @@ -75,10 +75,50 @@ LL | #[patchable_function_entry(prefix_nops = 255, prefix_nops = 255)] help: must be of the form | LL - #[patchable_function_entry(prefix_nops = 255, prefix_nops = 255)] -LL + #[patchable_function_entry(prefix_nops = m, entry_nops = n)] +LL + #[patchable_function_entry(prefix_nops = m, entry_nops = n, section = "section")] | -error: aborting due to 6 previous errors +error[E0539]: malformed `patchable_function_entry` attribute input + --> $DIR/patchable-function-entry-attribute.rs:28:1 + | +LL | #[patchable_function_entry(section = 255)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---^^ + | | + | expected a string literal here + | +help: must be of the form + | +LL - #[patchable_function_entry(section = 255)] +LL + #[patchable_function_entry(prefix_nops = m, entry_nops = n, section = "section")] + | + +error[E0538]: malformed `patchable_function_entry` attribute input + --> $DIR/patchable-function-entry-attribute.rs:32:1 + | +LL | #[patchable_function_entry(section = "foo", section = "bar")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------^^^^^^^^^^ + | | + | found `section` used as a key more than once + | +help: must be of the form + | +LL - #[patchable_function_entry(section = "foo", section = "bar")] +LL + #[patchable_function_entry(prefix_nops = m, entry_nops = n, section = "section")] + | + +error[E0648]: `section` may not contain null characters + --> $DIR/patchable-function-entry-attribute.rs:36:38 + | +LL | #[patchable_function_entry(section = "fo\0o")] + | ^^^^^^^ + +error: `section` may not be empty + --> $DIR/patchable-function-entry-attribute.rs:40:38 + | +LL | #[patchable_function_entry(section = "")] + | ^^ + +error: aborting due to 10 previous errors -Some errors have detailed explanations: E0538, E0539. +Some errors have detailed explanations: E0538, E0539, E0648. For more information about an error, try `rustc --explain E0538`. diff --git a/tests/ui/patchable-function-entry/patchable-function-entry-flags.stderr b/tests/ui/patchable-function-entry/patchable-function-entry-flags.stderr index b09af94a61541..bde7f4aa9dff6 100644 --- a/tests/ui/patchable-function-entry/patchable-function-entry-flags.stderr +++ b/tests/ui/patchable-function-entry/patchable-function-entry-flags.stderr @@ -1,2 +1,2 @@ -error: incorrect value `1,2` for unstable option `patchable-function-entry` - either two comma separated integers (total_nops,prefix_nops), with prefix_nops <= total_nops, or one integer (total_nops) was expected +error: incorrect value `1,2` for unstable option `patchable-function-entry` - a comma separated list of (prefix_nops,total_nops,section_name), (prefix_nops,total_nops), or (total_nops). Where prefix_nops <= total_nops where 0 < total_nops <= 255 and prefix_nops <= total_nops was expected