@@ -8,9 +8,9 @@ use rustc_span::edition::Edition::Edition2024;
88use super :: prelude:: * ;
99use crate :: attributes:: AttributeSafety ;
1010use crate :: session_diagnostics:: {
11- EmptyExportName , NakedFunctionIncompatibleAttribute , NullOnExport , NullOnObjcClass ,
12- NullOnObjcSelector , ObjcClassExpectedStringLiteral , ObjcSelectorExpectedStringLiteral ,
13- SanitizeInvalidStatic , TargetFeatureOnLangItem ,
11+ EmptyExportName , EmptySection , NakedFunctionIncompatibleAttribute , NullOnExport ,
12+ NullOnObjcClass , NullOnObjcSelector , NullOnSection , ObjcClassExpectedStringLiteral ,
13+ ObjcSelectorExpectedStringLiteral , SanitizeInvalidStatic , TargetFeatureOnLangItem ,
1414} ;
1515use crate :: target_checking:: Policy :: AllowSilent ;
1616
@@ -795,82 +795,94 @@ pub(crate) struct PatchableFunctionEntryParser;
795795impl SingleAttributeParser for PatchableFunctionEntryParser {
796796 const PATH : & [ Symbol ] = & [ sym:: patchable_function_entry] ;
797797 const ALLOWED_TARGETS : AllowedTargets < ' _ > = AllowedTargets :: AllowList ( & [ Allow ( Target :: Fn ) ] ) ;
798- const TEMPLATE : AttributeTemplate = template ! ( List : & [ "prefix_nops = m, entry_nops = n" ] ) ;
798+ const TEMPLATE : AttributeTemplate =
799+ template ! ( List : & [ "prefix_nops = m, entry_nops = n, section = \" section\" " ] ) ;
799800 const STABILITY : AttributeStability = unstable ! ( patchable_function_entry) ;
800801
801802 fn convert ( cx : & mut AcceptContext < ' _ , ' _ > , args : & ArgParser ) -> Option < AttributeKind > {
802803 let meta_item_list = cx. expect_list ( args, cx. attr_span ) ?;
803804
804805 let mut prefix = None ;
805806 let mut entry = None ;
807+ let mut section = None ;
806808
807809 if meta_item_list. len ( ) == 0 {
808810 cx. adcx ( ) . expected_at_least_one_argument ( meta_item_list. span ) ;
809811 return None ;
810812 }
811813
812- let mut errored = false ;
813-
814814 for item in meta_item_list. mixed ( ) {
815815 let Some ( ( ident, value) ) = cx. expect_name_value ( item, item. span ( ) , None ) else {
816- continue ;
816+ return None ;
817817 } ;
818818
819819 let attrib_to_write = match ident. name {
820820 sym:: prefix_nops => {
821821 // Duplicate prefixes are not allowed
822822 if prefix. is_some ( ) {
823- errored = true ;
824823 cx. adcx ( ) . duplicate_key ( ident. span , sym:: prefix_nops) ;
825- continue ;
824+ return None ;
826825 }
827826 & mut prefix
828827 }
829828 sym:: entry_nops => {
830829 // Duplicate entries are not allowed
831830 if entry. is_some ( ) {
832- errored = true ;
833831 cx. adcx ( ) . duplicate_key ( ident. span , sym:: entry_nops) ;
834- continue ;
832+ return None ;
835833 }
836834 & mut entry
837835 }
836+ sym:: section => {
837+ // Duplicate entries are not allowed
838+ if section. is_some ( ) {
839+ cx. adcx ( ) . duplicate_key ( ident. span , sym:: section) ;
840+ return None ;
841+ }
842+ // Only a string type value is allowed.
843+ let Some ( value_str) = value. value_as_str ( ) else {
844+ cx. adcx ( ) . expect_string_literal ( value) ;
845+ return None ;
846+ } ;
847+ // The section name does not allow null characters.
848+ if value_str. as_str ( ) . contains ( '\0' ) {
849+ cx. emit_err ( NullOnSection { span : value. value_span } ) ;
850+ }
851+ // The section name is not allowed to be empty, LLVM does
852+ // not allow them.
853+ if value_str. is_empty ( ) {
854+ cx. emit_err ( EmptySection { span : value. value_span } ) ;
855+ }
856+ section = Some ( value_str) ;
857+ // Integer parsing is not needed, process next item.
858+ continue ;
859+ }
838860 _ => {
839- errored = true ;
840861 cx. adcx ( ) . expected_specific_argument (
841862 ident. span ,
842863 & [ sym:: prefix_nops, sym:: entry_nops] ,
843864 ) ;
844- continue ;
865+ return None ;
845866 }
846867 } ;
847868
848869 let rustc_ast:: LitKind :: Int ( val, _) = value. value_as_lit ( ) . kind else {
849- errored = true ;
850870 cx. adcx ( ) . expected_integer_literal ( value. value_span ) ;
851- continue ;
871+ return None ;
852872 } ;
853873
854874 let Ok ( val) = val. get ( ) . try_into ( ) else {
855- errored = true ;
856875 cx. adcx ( ) . expected_integer_literal_in_range (
857876 value. value_span ,
858877 u8:: MIN as isize ,
859878 u8:: MAX as isize ,
860879 ) ;
861- continue ;
880+ return None ;
862881 } ;
863882
864883 * attrib_to_write = Some ( val) ;
865884 }
866885
867- if errored {
868- None
869- } else {
870- Some ( AttributeKind :: PatchableFunctionEntry {
871- prefix : prefix. unwrap_or ( 0 ) ,
872- entry : entry. unwrap_or ( 0 ) ,
873- } )
874- }
886+ Some ( AttributeKind :: PatchableFunctionEntry { prefix, entry, section } )
875887 }
876888}
0 commit comments