forked from Imagelibrary/binutils-gdb
RISC-V: Implment the merge logic for GNU_PROPERTY_RISCV_FEATURE_1_AND
GNU_PROPERTY_RISCV_FEATURE_1_AND will perform a bitwise AND operation on the properties of the input files.
This commit is contained in:
@@ -177,6 +177,8 @@ struct _bfd_riscv_elf_obj_tdata
|
||||
/* tls_type for each local got entry. */
|
||||
char *local_got_tls_type;
|
||||
|
||||
/* All GNU_PROPERTY_RISCV_FEATURE_1_AND properties. */
|
||||
uint32_t gnu_and_prop;
|
||||
/* PLT type. */
|
||||
riscv_plt_type plt_type;
|
||||
};
|
||||
@@ -5809,6 +5811,36 @@ riscv_elf_merge_symbol_attribute (struct elf_link_hash_entry *h,
|
||||
h->other |= STO_RISCV_VARIANT_CC;
|
||||
}
|
||||
|
||||
/* Implement elf_backend_setup_gnu_properties for RISC-V. It serves as a
|
||||
wrapper function for _bfd_riscv_elf_link_setup_gnu_properties to account
|
||||
for the effect of GNU properties of the output_bfd. */
|
||||
|
||||
static bfd *
|
||||
elfNN_riscv_link_setup_gnu_properties (struct bfd_link_info *info)
|
||||
{
|
||||
uint32_t and_prop = _bfd_riscv_elf_tdata (info->output_bfd)->gnu_and_prop;
|
||||
|
||||
bfd *pbfd = _bfd_riscv_elf_link_setup_gnu_properties (info, &and_prop);
|
||||
|
||||
_bfd_riscv_elf_tdata (info->output_bfd)->gnu_and_prop = and_prop;
|
||||
return pbfd;
|
||||
}
|
||||
|
||||
/* Implement elf_backend_merge_gnu_properties for RISC-V. It serves as a
|
||||
wrapper function for _bfd_riscv_elf_merge_gnu_properties to account
|
||||
for the effect of GNU properties of the output_bfd. */
|
||||
|
||||
static bool
|
||||
elfNN_riscv_merge_gnu_properties (struct bfd_link_info *info, bfd *abfd,
|
||||
bfd *bbfd ATTRIBUTE_UNUSED,
|
||||
elf_property *aprop, elf_property *bprop)
|
||||
{
|
||||
uint32_t and_prop = _bfd_riscv_elf_tdata (info->output_bfd)->gnu_and_prop;
|
||||
|
||||
return _bfd_riscv_elf_merge_gnu_properties (info, abfd, aprop, bprop,
|
||||
and_prop);
|
||||
}
|
||||
|
||||
#define TARGET_LITTLE_SYM riscv_elfNN_vec
|
||||
#define TARGET_LITTLE_NAME "elfNN-littleriscv"
|
||||
#define TARGET_BIG_SYM riscv_elfNN_be_vec
|
||||
@@ -5848,6 +5880,9 @@ riscv_elf_merge_symbol_attribute (struct elf_link_hash_entry *h,
|
||||
|
||||
#define elf_backend_init_index_section _bfd_elf_init_1_index_section
|
||||
|
||||
#define elf_backend_setup_gnu_properties elfNN_riscv_link_setup_gnu_properties
|
||||
#define elf_backend_merge_gnu_properties elfNN_riscv_merge_gnu_properties
|
||||
|
||||
#define elf_backend_can_gc_sections 1
|
||||
#define elf_backend_can_refcount 1
|
||||
#define elf_backend_want_got_plt 1
|
||||
|
||||
@@ -3366,3 +3366,174 @@ riscv_print_extensions (void)
|
||||
}
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
/* Find the first input bfd with GNU property and merge it with GPROP. If no
|
||||
such input is found, add it to a new section at the last input. Update
|
||||
GPROP accordingly. */
|
||||
|
||||
bfd *
|
||||
_bfd_riscv_elf_link_setup_gnu_properties (struct bfd_link_info *info,
|
||||
uint32_t *and_prop_p)
|
||||
{
|
||||
asection *sec;
|
||||
bfd *pbfd;
|
||||
bfd *ebfd = NULL;
|
||||
elf_property *prop;
|
||||
|
||||
uint32_t and_prop = *and_prop_p;
|
||||
|
||||
/* Find a normal input file with GNU property note. */
|
||||
for (pbfd = info->input_bfds; pbfd != NULL; pbfd = pbfd->link.next)
|
||||
if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour
|
||||
&& bfd_count_sections (pbfd) != 0)
|
||||
{
|
||||
ebfd = pbfd;
|
||||
|
||||
if (elf_properties (pbfd) != NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
/* If ebfd != NULL it is either an input with property note or the last
|
||||
input. Either way if we have and_prop, we should add it (by
|
||||
creating a section if needed). */
|
||||
if (ebfd != NULL && (and_prop))
|
||||
{
|
||||
prop = _bfd_elf_get_property (ebfd, GNU_PROPERTY_RISCV_FEATURE_1_AND, 4);
|
||||
|
||||
prop->u.number |= and_prop;
|
||||
prop->pr_kind = property_number;
|
||||
|
||||
/* pbfd being NULL implies ebfd is the last input. Create the GNU
|
||||
property note section. */
|
||||
if (pbfd == NULL)
|
||||
{
|
||||
sec
|
||||
= bfd_make_section_with_flags (ebfd, NOTE_GNU_PROPERTY_SECTION_NAME,
|
||||
(SEC_ALLOC | SEC_LOAD | SEC_IN_MEMORY
|
||||
| SEC_READONLY | SEC_HAS_CONTENTS
|
||||
| SEC_DATA));
|
||||
if (sec == NULL)
|
||||
info->callbacks->einfo (
|
||||
_ ("%F%P: failed to create GNU property section\n"));
|
||||
|
||||
elf_section_type (sec) = SHT_NOTE;
|
||||
}
|
||||
}
|
||||
|
||||
pbfd = _bfd_elf_link_setup_gnu_properties (info);
|
||||
|
||||
if (bfd_link_relocatable (info))
|
||||
return pbfd;
|
||||
|
||||
/* If pbfd has any GNU_PROPERTY_RISCV_FEATURE_1_AND properties, update
|
||||
and_prop accordingly. */
|
||||
if (pbfd != NULL)
|
||||
{
|
||||
elf_property_list *p;
|
||||
elf_property_list *plist = elf_properties (pbfd);
|
||||
|
||||
if ((p = _bfd_elf_find_property (plist, GNU_PROPERTY_RISCV_FEATURE_1_AND,
|
||||
NULL))
|
||||
!= NULL)
|
||||
and_prop = p->property.u.number
|
||||
& (GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED
|
||||
| GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS);
|
||||
}
|
||||
|
||||
*and_prop_p = and_prop;
|
||||
return pbfd;
|
||||
}
|
||||
|
||||
/* Define elf_backend_parse_gnu_properties for RISC-V. */
|
||||
|
||||
enum elf_property_kind
|
||||
_bfd_riscv_elf_parse_gnu_properties (bfd *abfd, unsigned int type,
|
||||
bfd_byte *ptr, unsigned int datasz)
|
||||
{
|
||||
elf_property *prop;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case GNU_PROPERTY_RISCV_FEATURE_1_AND:
|
||||
if (datasz != 4)
|
||||
{
|
||||
_bfd_error_handler (_ (
|
||||
"error: %pB: <corrupt RISC-V used size: 0x%x>"),
|
||||
abfd, datasz);
|
||||
return property_corrupt;
|
||||
}
|
||||
prop = _bfd_elf_get_property (abfd, type, datasz);
|
||||
/* Combine properties of the same type. */
|
||||
prop->u.number |= bfd_h_get_32 (abfd, ptr);
|
||||
prop->pr_kind = property_number;
|
||||
break;
|
||||
|
||||
default:
|
||||
return property_ignored;
|
||||
}
|
||||
|
||||
return property_number;
|
||||
}
|
||||
|
||||
/* Merge RISC-V GNU property BPROP with APROP also accounting for PROP.
|
||||
If APROP isn't NULL, merge it with BPROP and/or PROP. Vice-versa if BROP
|
||||
isn't NULL. Return TRUE if there is any update to APROP or if BPROP should
|
||||
be merge with ABFD. */
|
||||
|
||||
bool
|
||||
_bfd_riscv_elf_merge_gnu_properties
|
||||
(struct bfd_link_info *info ATTRIBUTE_UNUSED, bfd *abfd ATTRIBUTE_UNUSED,
|
||||
elf_property *aprop, elf_property *bprop, uint32_t and_prop)
|
||||
{
|
||||
unsigned int orig_number;
|
||||
bool updated = false;
|
||||
unsigned int pr_type = aprop != NULL ? aprop->pr_type : bprop->pr_type;
|
||||
|
||||
switch (pr_type)
|
||||
{
|
||||
case GNU_PROPERTY_RISCV_FEATURE_1_AND: {
|
||||
if (aprop != NULL && bprop != NULL)
|
||||
{
|
||||
orig_number = aprop->u.number;
|
||||
aprop->u.number = (orig_number & bprop->u.number) | and_prop;
|
||||
updated = orig_number != aprop->u.number;
|
||||
/* Remove the property if all feature bits are cleared. */
|
||||
if (aprop->u.number == 0)
|
||||
aprop->pr_kind = property_remove;
|
||||
break;
|
||||
}
|
||||
/* If either is NULL, the AND would be 0 so, if there is
|
||||
any PROP, asign it to the input that is not NULL. */
|
||||
if (and_prop)
|
||||
{
|
||||
if (aprop != NULL)
|
||||
{
|
||||
orig_number = aprop->u.number;
|
||||
aprop->u.number = and_prop;
|
||||
updated = orig_number != aprop->u.number;
|
||||
}
|
||||
else if (bprop != NULL)
|
||||
{
|
||||
bprop->u.number = and_prop;
|
||||
updated = true;
|
||||
}
|
||||
/* Shouldn't happen because we checked one of APROP or BPROP !=
|
||||
* NULL. */
|
||||
else
|
||||
abort ();
|
||||
}
|
||||
/* No PROP and BPROP is NULL, so remove APROP. */
|
||||
else if (!and_prop && bprop == NULL && aprop != NULL)
|
||||
{
|
||||
aprop->pr_kind = property_remove;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
@@ -133,3 +133,16 @@ extern void
|
||||
bfd_elf32_riscv_set_data_segment_info (struct bfd_link_info *, int *);
|
||||
extern void
|
||||
bfd_elf64_riscv_set_data_segment_info (struct bfd_link_info *, int *);
|
||||
|
||||
extern bfd *
|
||||
_bfd_riscv_elf_link_setup_gnu_properties (struct bfd_link_info *, uint32_t *);
|
||||
|
||||
extern enum elf_property_kind
|
||||
_bfd_riscv_elf_parse_gnu_properties (bfd *, unsigned int, bfd_byte *,
|
||||
unsigned int);
|
||||
|
||||
extern bool
|
||||
_bfd_riscv_elf_merge_gnu_properties (struct bfd_link_info *, bfd *,
|
||||
elf_property *, elf_property *, uint32_t);
|
||||
|
||||
#define elf_backend_parse_gnu_properties _bfd_riscv_elf_parse_gnu_properties
|
||||
|
||||
@@ -227,6 +227,12 @@ if [istarget "riscv*-*-*"] {
|
||||
run_dump_test "data-reloc-rv64-addr32-pic"
|
||||
run_dump_test "data-reloc-rv64-undef32-pic"
|
||||
|
||||
run_dump_test "property-zicfilp-unlabeled"
|
||||
run_dump_test "property-zicfiss"
|
||||
run_dump_test "property-combine-and-1"
|
||||
run_dump_test "property-combine-and-2"
|
||||
run_dump_test "property-combine-and-3"
|
||||
|
||||
# IFUNC testcases.
|
||||
# Check IFUNC by single type relocs.
|
||||
run_dump_test_ifunc "ifunc-reloc-call-01" rv32 exe
|
||||
|
||||
6
ld/testsuite/ld-riscv-elf/property-combine-and-1.d
Normal file
6
ld/testsuite/ld-riscv-elf/property-combine-and-1.d
Normal file
@@ -0,0 +1,6 @@
|
||||
#name: RISC-V GNU Property (multiple inputs, combine section) - 1
|
||||
#source: property1.s
|
||||
#source: property2.s
|
||||
#as: -march=rv64g
|
||||
#ld: -shared
|
||||
#readelf: -n
|
||||
11
ld/testsuite/ld-riscv-elf/property-combine-and-2.d
Normal file
11
ld/testsuite/ld-riscv-elf/property-combine-and-2.d
Normal file
@@ -0,0 +1,11 @@
|
||||
#name: RISC-V GNU Property (multiple inputs, combine section) - 2
|
||||
#source: property1.s
|
||||
#source: property3.s
|
||||
#as: -march=rv64g
|
||||
#ld: -shared
|
||||
#readelf: -n
|
||||
|
||||
Displaying notes found in: .note.gnu.property
|
||||
[ ]+Owner[ ]+Data size[ ]+Description
|
||||
[ ]+GNU[ ]+0x00000010[ ]+NT_GNU_PROPERTY_TYPE_0
|
||||
[ ]+Properties: RISC-V AND feature: CFI_LP_UNLABELED
|
||||
11
ld/testsuite/ld-riscv-elf/property-combine-and-3.d
Normal file
11
ld/testsuite/ld-riscv-elf/property-combine-and-3.d
Normal file
@@ -0,0 +1,11 @@
|
||||
#name: RISC-V GNU Property (multiple inputs, combine section) - 3
|
||||
#source: property1.s
|
||||
#source: property4.s
|
||||
#as: -march=rv64g
|
||||
#ld: -shared
|
||||
#readelf: -n
|
||||
|
||||
Displaying notes found in: .note.gnu.property
|
||||
[ ]+Owner[ ]+Data size[ ]+Description
|
||||
[ ]+GNU[ ]+0x00000010[ ]+NT_GNU_PROPERTY_TYPE_0
|
||||
[ ]+Properties: RISC-V AND feature: CFI_SS
|
||||
10
ld/testsuite/ld-riscv-elf/property-zicfilp-unlabeled.d
Normal file
10
ld/testsuite/ld-riscv-elf/property-zicfilp-unlabeled.d
Normal file
@@ -0,0 +1,10 @@
|
||||
#name: GNU Property (single input, CFI_LP_UNLABELED)
|
||||
#source: property-zicfilp-unlabeled.s
|
||||
#as: -march=rv64g
|
||||
#ld: -shared
|
||||
#readelf: -n
|
||||
|
||||
Displaying notes found in: .note.gnu.property
|
||||
[ ]+Owner[ ]+Data size[ ]+Description
|
||||
[ ]+GNU[ ]+0x00000010[ ]+NT_GNU_PROPERTY_TYPE_0
|
||||
[ ]+Properties: RISC-V AND feature: CFI_LP_UNLABELED
|
||||
21
ld/testsuite/ld-riscv-elf/property-zicfilp-unlabeled.s
Normal file
21
ld/testsuite/ld-riscv-elf/property-zicfilp-unlabeled.s
Normal file
@@ -0,0 +1,21 @@
|
||||
.text
|
||||
.globl _start
|
||||
.type _start,@function
|
||||
_start:
|
||||
ret
|
||||
|
||||
.section ".note.gnu.property", "a"
|
||||
.p2align 3
|
||||
.long 1f - 0f /* name length */
|
||||
.long 5f - 2f /* data length */
|
||||
.long 5 /* note type */
|
||||
0: .asciz "GNU" /* vendor name */
|
||||
1:
|
||||
.p2align 3
|
||||
2: .long 0xc0000000 /* pr_type. */
|
||||
.long 4f - 3f /* pr_datasz. */
|
||||
3:
|
||||
.long 0x1 /* GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED. */
|
||||
4:
|
||||
.p2align 3
|
||||
5:
|
||||
10
ld/testsuite/ld-riscv-elf/property-zicfiss.d
Normal file
10
ld/testsuite/ld-riscv-elf/property-zicfiss.d
Normal file
@@ -0,0 +1,10 @@
|
||||
#name: GNU Property (single input, CFI_SS)
|
||||
#source: property-zicfiss.s
|
||||
#as: -march=rv64g
|
||||
#ld: -shared
|
||||
#readelf: -n
|
||||
|
||||
Displaying notes found in: .note.gnu.property
|
||||
[ ]+Owner[ ]+Data size[ ]+Description
|
||||
[ ]+GNU[ ]+0x00000010[ ]+NT_GNU_PROPERTY_TYPE_0
|
||||
[ ]+Properties: RISC-V AND feature: CFI_SS
|
||||
21
ld/testsuite/ld-riscv-elf/property-zicfiss.s
Normal file
21
ld/testsuite/ld-riscv-elf/property-zicfiss.s
Normal file
@@ -0,0 +1,21 @@
|
||||
.text
|
||||
.globl _start
|
||||
.type _start,@function
|
||||
_start:
|
||||
ret
|
||||
|
||||
.section ".note.gnu.property", "a"
|
||||
.p2align 3
|
||||
.long 1f - 0f /* name length */
|
||||
.long 5f - 2f /* data length */
|
||||
.long 5 /* note type */
|
||||
0: .asciz "GNU" /* vendor name */
|
||||
1:
|
||||
.p2align 3
|
||||
2: .long 0xc0000000 /* pr_type. */
|
||||
.long 4f - 3f /* pr_datasz. */
|
||||
3:
|
||||
.long 0x2 /* GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS. */
|
||||
4:
|
||||
.p2align 3
|
||||
5:
|
||||
21
ld/testsuite/ld-riscv-elf/property1.s
Normal file
21
ld/testsuite/ld-riscv-elf/property1.s
Normal file
@@ -0,0 +1,21 @@
|
||||
.text
|
||||
.globl _start
|
||||
.type _start,@function
|
||||
_start:
|
||||
ret
|
||||
|
||||
.section ".note.gnu.property", "a"
|
||||
.p2align 3
|
||||
.long 1f - 0f /* name length */
|
||||
.long 5f - 2f /* data length */
|
||||
.long 5 /* note type */
|
||||
0: .asciz "GNU" /* vendor name */
|
||||
1:
|
||||
.p2align 3
|
||||
2: .long 0xc0000000 /* pr_type. */
|
||||
.long 4f - 3f /* pr_datasz. */
|
||||
3:
|
||||
.long 0x3 /* CFI_LP_UNLABELED and CFI_SS. */
|
||||
4:
|
||||
.p2align 3
|
||||
5:
|
||||
5
ld/testsuite/ld-riscv-elf/property2.s
Normal file
5
ld/testsuite/ld-riscv-elf/property2.s
Normal file
@@ -0,0 +1,5 @@
|
||||
.text
|
||||
.globl foo
|
||||
.type foo,@function
|
||||
foo:
|
||||
ret
|
||||
21
ld/testsuite/ld-riscv-elf/property3.s
Normal file
21
ld/testsuite/ld-riscv-elf/property3.s
Normal file
@@ -0,0 +1,21 @@
|
||||
.text
|
||||
.globl _start
|
||||
.type _start,@function
|
||||
bar:
|
||||
ret
|
||||
|
||||
.section ".note.gnu.property", "a"
|
||||
.p2align 3
|
||||
.long 1f - 0f /* name length */
|
||||
.long 5f - 2f /* data length */
|
||||
.long 5 /* note type */
|
||||
0: .asciz "GNU" /* vendor name */
|
||||
1:
|
||||
.p2align 3
|
||||
2: .long 0xc0000000 /* pr_type. */
|
||||
.long 4f - 3f /* pr_datasz. */
|
||||
3:
|
||||
.long 0x1 /* CFI_LP_UNLABELED. */
|
||||
4:
|
||||
.p2align 3
|
||||
5:
|
||||
21
ld/testsuite/ld-riscv-elf/property4.s
Normal file
21
ld/testsuite/ld-riscv-elf/property4.s
Normal file
@@ -0,0 +1,21 @@
|
||||
.text
|
||||
.globl _start
|
||||
.type _start,@function
|
||||
zoo:
|
||||
ret
|
||||
|
||||
.section ".note.gnu.property", "a"
|
||||
.p2align 3
|
||||
.long 1f - 0f /* name length */
|
||||
.long 5f - 2f /* data length */
|
||||
.long 5 /* note type */
|
||||
0: .asciz "GNU" /* vendor name */
|
||||
1:
|
||||
.p2align 3
|
||||
2: .long 0xc0000000 /* pr_type. */
|
||||
.long 4f - 3f /* pr_datasz. */
|
||||
3:
|
||||
.long 0x2 /* CFI_LP_SS. */
|
||||
4:
|
||||
.p2align 3
|
||||
5:
|
||||
Reference in New Issue
Block a user