@@ -3366,3 +3366,174 @@ riscv_print_extensions (void)
33663366 }
33673367 printf ("\n" );
33683368}
3369+
3370+ /* Find the first input bfd with GNU property and merge it with GPROP. If no
3371+ such input is found, add it to a new section at the last input. Update
3372+ GPROP accordingly. */
3373+
3374+ bfd *
3375+ _bfd_riscv_elf_link_setup_gnu_properties (struct bfd_link_info * info ,
3376+ uint32_t * and_prop_p )
3377+ {
3378+ asection * sec ;
3379+ bfd * pbfd ;
3380+ bfd * ebfd = NULL ;
3381+ elf_property * prop ;
3382+
3383+ uint32_t and_prop = * and_prop_p ;
3384+
3385+ /* Find a normal input file with GNU property note. */
3386+ for (pbfd = info -> input_bfds ; pbfd != NULL ; pbfd = pbfd -> link .next )
3387+ if (bfd_get_flavour (pbfd ) == bfd_target_elf_flavour
3388+ && bfd_count_sections (pbfd ) != 0 )
3389+ {
3390+ ebfd = pbfd ;
3391+
3392+ if (elf_properties (pbfd ) != NULL )
3393+ break ;
3394+ }
3395+
3396+ /* If ebfd != NULL it is either an input with property note or the last
3397+ input. Either way if we have and_prop, we should add it (by
3398+ creating a section if needed). */
3399+ if (ebfd != NULL && (and_prop ))
3400+ {
3401+ prop = _bfd_elf_get_property (ebfd , GNU_PROPERTY_RISCV_FEATURE_1_AND , 4 );
3402+
3403+ prop -> u .number |= and_prop ;
3404+ prop -> pr_kind = property_number ;
3405+
3406+ /* pbfd being NULL implies ebfd is the last input. Create the GNU
3407+ property note section. */
3408+ if (pbfd == NULL )
3409+ {
3410+ sec
3411+ = bfd_make_section_with_flags (ebfd , NOTE_GNU_PROPERTY_SECTION_NAME ,
3412+ (SEC_ALLOC | SEC_LOAD | SEC_IN_MEMORY
3413+ | SEC_READONLY | SEC_HAS_CONTENTS
3414+ | SEC_DATA ));
3415+ if (sec == NULL )
3416+ info -> callbacks -> einfo (
3417+ _ ("%F%P: failed to create GNU property section\n" ));
3418+
3419+ elf_section_type (sec ) = SHT_NOTE ;
3420+ }
3421+ }
3422+
3423+ pbfd = _bfd_elf_link_setup_gnu_properties (info );
3424+
3425+ if (bfd_link_relocatable (info ))
3426+ return pbfd ;
3427+
3428+ /* If pbfd has any GNU_PROPERTY_RISCV_FEATURE_1_AND properties, update
3429+ and_prop accordingly. */
3430+ if (pbfd != NULL )
3431+ {
3432+ elf_property_list * p ;
3433+ elf_property_list * plist = elf_properties (pbfd );
3434+
3435+ if ((p = _bfd_elf_find_property (plist , GNU_PROPERTY_RISCV_FEATURE_1_AND ,
3436+ NULL ))
3437+ != NULL )
3438+ and_prop = p -> property .u .number
3439+ & (GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED
3440+ | GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS );
3441+ }
3442+
3443+ * and_prop_p = and_prop ;
3444+ return pbfd ;
3445+ }
3446+
3447+ /* Define elf_backend_parse_gnu_properties for RISC-V. */
3448+
3449+ enum elf_property_kind
3450+ _bfd_riscv_elf_parse_gnu_properties (bfd * abfd , unsigned int type ,
3451+ bfd_byte * ptr , unsigned int datasz )
3452+ {
3453+ elf_property * prop ;
3454+
3455+ switch (type )
3456+ {
3457+ case GNU_PROPERTY_RISCV_FEATURE_1_AND :
3458+ if (datasz != 4 )
3459+ {
3460+ _bfd_error_handler (_ (
3461+ "error: %pB: <corrupt RISC-V used size: 0x%x>" ),
3462+ abfd , datasz );
3463+ return property_corrupt ;
3464+ }
3465+ prop = _bfd_elf_get_property (abfd , type , datasz );
3466+ /* Combine properties of the same type. */
3467+ prop -> u .number |= bfd_h_get_32 (abfd , ptr );
3468+ prop -> pr_kind = property_number ;
3469+ break ;
3470+
3471+ default :
3472+ return property_ignored ;
3473+ }
3474+
3475+ return property_number ;
3476+ }
3477+
3478+ /* Merge RISC-V GNU property BPROP with APROP also accounting for PROP.
3479+ If APROP isn't NULL, merge it with BPROP and/or PROP. Vice-versa if BROP
3480+ isn't NULL. Return TRUE if there is any update to APROP or if BPROP should
3481+ be merge with ABFD. */
3482+
3483+ bool
3484+ _bfd_riscv_elf_merge_gnu_properties
3485+ (struct bfd_link_info * info ATTRIBUTE_UNUSED , bfd * abfd ATTRIBUTE_UNUSED ,
3486+ elf_property * aprop , elf_property * bprop , uint32_t and_prop )
3487+ {
3488+ unsigned int orig_number ;
3489+ bool updated = false;
3490+ unsigned int pr_type = aprop != NULL ? aprop -> pr_type : bprop -> pr_type ;
3491+
3492+ switch (pr_type )
3493+ {
3494+ case GNU_PROPERTY_RISCV_FEATURE_1_AND : {
3495+ if (aprop != NULL && bprop != NULL )
3496+ {
3497+ orig_number = aprop -> u .number ;
3498+ aprop -> u .number = (orig_number & bprop -> u .number ) | and_prop ;
3499+ updated = orig_number != aprop -> u .number ;
3500+ /* Remove the property if all feature bits are cleared. */
3501+ if (aprop -> u .number == 0 )
3502+ aprop -> pr_kind = property_remove ;
3503+ break ;
3504+ }
3505+ /* If either is NULL, the AND would be 0 so, if there is
3506+ any PROP, asign it to the input that is not NULL. */
3507+ if (and_prop )
3508+ {
3509+ if (aprop != NULL )
3510+ {
3511+ orig_number = aprop -> u .number ;
3512+ aprop -> u .number = and_prop ;
3513+ updated = orig_number != aprop -> u .number ;
3514+ }
3515+ else if (bprop != NULL )
3516+ {
3517+ bprop -> u .number = and_prop ;
3518+ updated = true;
3519+ }
3520+ /* Shouldn't happen because we checked one of APROP or BPROP !=
3521+ * NULL. */
3522+ else
3523+ abort ();
3524+ }
3525+ /* No PROP and BPROP is NULL, so remove APROP. */
3526+ else if (!and_prop && bprop == NULL && aprop != NULL )
3527+ {
3528+ aprop -> pr_kind = property_remove ;
3529+ updated = true;
3530+ }
3531+ }
3532+ break ;
3533+
3534+ default :
3535+ abort ();
3536+ }
3537+
3538+ return updated ;
3539+ }
0 commit comments