@@ -3463,3 +3463,174 @@ riscv_print_extensions (void)
34633463 }
34643464 printf ("\n" );
34653465}
3466+
3467+ /* Find the first input bfd with GNU property and merge it with GPROP. If no
3468+ such input is found, add it to a new section at the last input. Update
3469+ GPROP accordingly. */
3470+
3471+ bfd *
3472+ _bfd_riscv_elf_link_setup_gnu_properties (struct bfd_link_info * info ,
3473+ uint32_t * and_prop_p )
3474+ {
3475+ asection * sec ;
3476+ bfd * pbfd ;
3477+ bfd * ebfd = NULL ;
3478+ elf_property * prop ;
3479+
3480+ uint32_t and_prop = * and_prop_p ;
3481+
3482+ /* Find a normal input file with GNU property note. */
3483+ for (pbfd = info -> input_bfds ; pbfd != NULL ; pbfd = pbfd -> link .next )
3484+ if (bfd_get_flavour (pbfd ) == bfd_target_elf_flavour
3485+ && bfd_count_sections (pbfd ) != 0 )
3486+ {
3487+ ebfd = pbfd ;
3488+
3489+ if (elf_properties (pbfd ) != NULL )
3490+ break ;
3491+ }
3492+
3493+ /* If ebfd != NULL it is either an input with property note or the last
3494+ input. Either way if we have and_prop, we should add it (by
3495+ creating a section if needed). */
3496+ if (ebfd != NULL && (and_prop ))
3497+ {
3498+ prop = _bfd_elf_get_property (ebfd , GNU_PROPERTY_RISCV_FEATURE_1_AND , 4 );
3499+
3500+ prop -> u .number |= and_prop ;
3501+ prop -> pr_kind = property_number ;
3502+
3503+ /* pbfd being NULL implies ebfd is the last input. Create the GNU
3504+ property note section. */
3505+ if (pbfd == NULL )
3506+ {
3507+ sec
3508+ = bfd_make_section_with_flags (ebfd , NOTE_GNU_PROPERTY_SECTION_NAME ,
3509+ (SEC_ALLOC | SEC_LOAD | SEC_IN_MEMORY
3510+ | SEC_READONLY | SEC_HAS_CONTENTS
3511+ | SEC_DATA ));
3512+ if (sec == NULL )
3513+ info -> callbacks -> einfo (
3514+ _ ("%F%P: failed to create GNU property section\n" ));
3515+
3516+ elf_section_type (sec ) = SHT_NOTE ;
3517+ }
3518+ }
3519+
3520+ pbfd = _bfd_elf_link_setup_gnu_properties (info );
3521+
3522+ if (bfd_link_relocatable (info ))
3523+ return pbfd ;
3524+
3525+ /* If pbfd has any GNU_PROPERTY_RISCV_FEATURE_1_AND properties, update
3526+ and_prop accordingly. */
3527+ if (pbfd != NULL )
3528+ {
3529+ elf_property_list * p ;
3530+ elf_property_list * plist = elf_properties (pbfd );
3531+
3532+ if ((p = _bfd_elf_find_property (plist , GNU_PROPERTY_RISCV_FEATURE_1_AND ,
3533+ NULL ))
3534+ != NULL )
3535+ and_prop = p -> property .u .number
3536+ & (GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED
3537+ | GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS );
3538+ }
3539+
3540+ * and_prop_p = and_prop ;
3541+ return pbfd ;
3542+ }
3543+
3544+ /* Define elf_backend_parse_gnu_properties for RISC-V. */
3545+
3546+ enum elf_property_kind
3547+ _bfd_riscv_elf_parse_gnu_properties (bfd * abfd , unsigned int type ,
3548+ bfd_byte * ptr , unsigned int datasz )
3549+ {
3550+ elf_property * prop ;
3551+
3552+ switch (type )
3553+ {
3554+ case GNU_PROPERTY_RISCV_FEATURE_1_AND :
3555+ if (datasz != 4 )
3556+ {
3557+ _bfd_error_handler (_ (
3558+ "error: %pB: <corrupt RISC-V used size: 0x%x>" ),
3559+ abfd , datasz );
3560+ return property_corrupt ;
3561+ }
3562+ prop = _bfd_elf_get_property (abfd , type , datasz );
3563+ /* Combine properties of the same type. */
3564+ prop -> u .number |= bfd_h_get_32 (abfd , ptr );
3565+ prop -> pr_kind = property_number ;
3566+ break ;
3567+
3568+ default :
3569+ return property_ignored ;
3570+ }
3571+
3572+ return property_number ;
3573+ }
3574+
3575+ /* Merge RISC-V GNU property BPROP with APROP also accounting for PROP.
3576+ If APROP isn't NULL, merge it with BPROP and/or PROP. Vice-versa if BROP
3577+ isn't NULL. Return TRUE if there is any update to APROP or if BPROP should
3578+ be merge with ABFD. */
3579+
3580+ bool
3581+ _bfd_riscv_elf_merge_gnu_properties
3582+ (struct bfd_link_info * info ATTRIBUTE_UNUSED , bfd * abfd ATTRIBUTE_UNUSED ,
3583+ elf_property * aprop , elf_property * bprop , uint32_t and_prop )
3584+ {
3585+ unsigned int orig_number ;
3586+ bool updated = false;
3587+ unsigned int pr_type = aprop != NULL ? aprop -> pr_type : bprop -> pr_type ;
3588+
3589+ switch (pr_type )
3590+ {
3591+ case GNU_PROPERTY_RISCV_FEATURE_1_AND : {
3592+ if (aprop != NULL && bprop != NULL )
3593+ {
3594+ orig_number = aprop -> u .number ;
3595+ aprop -> u .number = (orig_number & bprop -> u .number ) | and_prop ;
3596+ updated = orig_number != aprop -> u .number ;
3597+ /* Remove the property if all feature bits are cleared. */
3598+ if (aprop -> u .number == 0 )
3599+ aprop -> pr_kind = property_remove ;
3600+ break ;
3601+ }
3602+ /* If either is NULL, the AND would be 0 so, if there is
3603+ any PROP, asign it to the input that is not NULL. */
3604+ if (and_prop )
3605+ {
3606+ if (aprop != NULL )
3607+ {
3608+ orig_number = aprop -> u .number ;
3609+ aprop -> u .number = and_prop ;
3610+ updated = orig_number != aprop -> u .number ;
3611+ }
3612+ else if (bprop != NULL )
3613+ {
3614+ bprop -> u .number = and_prop ;
3615+ updated = true;
3616+ }
3617+ /* Shouldn't happen because we checked one of APROP or BPROP !=
3618+ * NULL. */
3619+ else
3620+ abort ();
3621+ }
3622+ /* No PROP and BPROP is NULL, so remove APROP. */
3623+ else if (!and_prop && bprop == NULL && aprop != NULL )
3624+ {
3625+ aprop -> pr_kind = property_remove ;
3626+ updated = true;
3627+ }
3628+ }
3629+ break ;
3630+
3631+ default :
3632+ abort ();
3633+ }
3634+
3635+ return updated ;
3636+ }
0 commit comments