@@ -142,6 +142,16 @@ riscv_get_priv_spec_class_from_numbers (unsigned int major,
*class = class_t;
}
+/* Check if the value of Tag_RISCV_x3_reg_usage is defined or not. */
+
+bool
+riscv_elf_is_unknown_x3_reg_usage (int value)
+{
+ return (value != X3_DEFAULT
+ && value != X3_RELAX
+ && value != X3_RESERVED);
+}
+
/* Define mapping symbols for riscv. */
bool
@@ -81,5 +81,15 @@ riscv_get_priv_spec_class_from_numbers (unsigned int,
unsigned int,
enum riscv_spec_class *);
+enum riscv_x3_reg_usage
+{
+ X3_DEFAULT = 0,
+ X3_RELAX,
+ X3_RESERVED = 4,
+};
+
+extern bool
+riscv_elf_is_unknown_x3_reg_usage (int);
+
extern bool
riscv_elf_is_mapping_symbols (const char *);
@@ -235,6 +235,9 @@ struct riscv_elf_link_hash_table
/* Relocations for variant CC symbols may be present. */
int variant_cc;
+
+ /* The usage of x3, will be updated to output elf attribute. */
+ int x3_reg_usage;
};
/* Instruction access functions. */
@@ -3852,6 +3855,15 @@ riscv_merge_attributes (bfd *ibfd, struct bfd_link_info *info)
initialized. */
out_attr[0].i = 1;
+ /* Filter the unknow value for Tag_RISCV_x3_reg_usage. */
+ if (riscv_elf_is_unknown_x3_reg_usage (out_attr[Tag_RISCV_x3_reg_usage].i))
+ out_attr[Tag_RISCV_x3_reg_usage].i = X3_DEFAULT;
+ /* Disable gp relaxations if x3 is reserved.
+ The priority of elf x3_reg_usage attribute is higher than the ld
+ --[no-]relax-gp options. */
+ if (out_attr[Tag_RISCV_x3_reg_usage].i == X3_RESERVED)
+ riscv_elf_hash_table (info)->params->relax_gp = false;
+
return true;
}
@@ -3968,6 +3980,30 @@ riscv_merge_attributes (bfd *ibfd, struct bfd_link_info *info)
}
break;
+ case Tag_RISCV_x3_reg_usage:
+ /* Filter the unknow value for Tag_RISCV_x3_reg_usage. */
+ if (riscv_elf_is_unknown_x3_reg_usage (in_attr[Tag_RISCV_x3_reg_usage].i))
+ in_attr[Tag_RISCV_x3_reg_usage].i = X3_DEFAULT;
+
+ if (out_attr[i].i == X3_DEFAULT)
+ out_attr[i].i = in_attr[i].i;
+ else if (in_attr[i].i != X3_DEFAULT
+ && out_attr[i].i != in_attr[i].i)
+ {
+ _bfd_error_handler
+ (_("error: %pB use Tag_RISCV_x3_reg_usage (%d) but output "
+ "use Tag_RISCV_x3_reg_usage (%d)"),
+ ibfd, in_attr[i].i, out_attr[i].i);
+ result = false;
+ }
+
+ /* Disable gp relaxations if x3 is reserved.
+ The priority of elf x3_reg_usage attribute is higher than the ld
+ --[no-]relax-gp options. */
+ if (out_attr[i].i == X3_RESERVED)
+ riscv_elf_hash_table (info)->params->relax_gp = false;
+ break;
+
default:
result &= _bfd_elf_merge_unknown_attribute_low (ibfd, obfd, i);
}
@@ -4635,6 +4671,9 @@ _bfd_riscv_relax_lui (bfd *abfd,
|| (symval < gp
&& VALID_ITYPE_IMM (symval - gp - max_alignment - reserve_size)))
{
+ if (!undefined_weak && gp)
+ htab->x3_reg_usage = X3_RELAX;
+
unsigned sym = ELFNN_R_SYM (rel->r_info);
switch (ELFNN_R_TYPE (rel->r_info))
{
@@ -4899,6 +4938,9 @@ _bfd_riscv_relax_pc (bfd *abfd ATTRIBUTE_UNUSED,
|| (symval < gp
&& VALID_ITYPE_IMM (symval - gp - max_alignment - reserve_size)))
{
+ if (!undefined_weak && gp)
+ htab->x3_reg_usage = X3_RELAX;
+
unsigned sym = hi_reloc.hi_sym;
switch (ELFNN_R_TYPE (rel->r_info))
{
@@ -4945,6 +4987,18 @@ bfd_elfNN_riscv_set_data_segment_info (struct bfd_link_info *info,
htab->data_segment_phase = data_segment_phase;
}
+/* Called by after_allocation, after all the relaxations (ldelf_map_segments)
+ finishing, to update the value of output Tag_RISCV_x3_reg_usage. */
+
+void
+bfd_elfNN_riscv_update_x3_reg_usage (struct bfd_link_info *info)
+{
+ struct riscv_elf_link_hash_table *htab = riscv_elf_hash_table (info);
+ enum riscv_x3_reg_usage x = htab->x3_reg_usage == X3_RELAX
+ ? X3_RELAX : X3_RESERVED;
+ bfd_elf_add_proc_attr_int (info->output_bfd, Tag_RISCV_x3_reg_usage, x);
+}
+
/* Relax a section.
Pass 0: Shortens code sequences for LUI/CALL/TPREL/PCREL relocs and
@@ -123,3 +123,8 @@ 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 void
+bfd_elf32_riscv_update_x3_reg_usage (struct bfd_link_info *);
+extern void
+bfd_elf64_riscv_update_x3_reg_usage (struct bfd_link_info *);
@@ -18475,6 +18475,7 @@ static struct riscv_attr_tag_t riscv_attr_tag[] =
T(priv_spec_revision),
T(unaligned_access),
T(stack_align),
+ T(x3_reg_usage),
#undef T
};
@@ -18531,6 +18532,21 @@ display_riscv_attribute (unsigned char *p,
case Tag_RISCV_arch:
p = display_tag_value (-1, p, end);
break;
+ case Tag_RISCV_x3_reg_usage:
+ READ_ULEB (val, p, end);
+ switch (val)
+ {
+ case 1:
+ printf (_("relaxation\n"));
+ break;
+ case 4:
+ printf (_("reserved\n"));
+ break;
+ default:
+ printf (_("unknown\n"));
+ break;
+ }
+ break;
default:
return display_tag_value (tag, p, end);
}
@@ -5036,6 +5036,7 @@ riscv_convert_symbolic_attribute (const char *name)
T(priv_spec_revision),
T(unaligned_access),
T(stack_align),
+ T(x3_reg_usage),
#undef T
};
@@ -5090,6 +5091,17 @@ s_riscv_attribute (int ignored ATTRIBUTE_UNUSED)
"any instructions"));
break;
+ /* The usage of x3,
+ 0: default.
+ 1: gp relaxation.
+ 4: reserved.
+ others: not defined yet. */
+ case Tag_RISCV_x3_reg_usage:
+ attr = elf_known_obj_attributes_proc (stdoutput);
+ if (riscv_elf_is_unknown_x3_reg_usage (attr[tag].i))
+ as_warn (_("unknown value for Tag_RISCV_x3_reg_usage"));
+ break;
+
default:
break;
}
new file mode 100644
@@ -0,0 +1,6 @@
+#as: -defsym __relax__=1
+#readelf: -A
+#source: attribute-x3-reg-usage.s
+
+#...
+ Tag_RISCV_x3_reg_usage: relaxation
new file mode 100644
@@ -0,0 +1,6 @@
+#as: -defsym __reserved__=1
+#readelf: -A
+#source: attribute-x3-reg-usage.s
+
+#...
+ Tag_RISCV_x3_reg_usage: reserved
new file mode 100644
@@ -0,0 +1,7 @@
+#as: -defsym __unknown__=1
+#readelf: -A
+#source: attribute-x3-reg-usage.s
+#warning_output: attribute-x3-reg-usage-unknown.l
+
+#...
+ Tag_RISCV_x3_reg_usage: unknown
new file mode 100644
@@ -0,0 +1,4 @@
+.*Assembler messages:
+.*Warning: unknown value for Tag_RISCV_x3_reg_usage
+.*Warning: unknown value for Tag_RISCV_x3_reg_usage
+.*Warning: unknown value for Tag_RISCV_x3_reg_usage
new file mode 100644
@@ -0,0 +1,13 @@
+.ifdef __relax__
+.attribute Tag_RISCV_x3_reg_usage, 1
+.endif
+
+.ifdef __reserved__
+.attribute Tag_RISCV_x3_reg_usage, 4
+.endif
+
+.ifdef __unknown__
+.attribute Tag_RISCV_x3_reg_usage, 2
+.attribute Tag_RISCV_x3_reg_usage, 3
+.attribute Tag_RISCV_x3_reg_usage, 5
+.endif
@@ -144,7 +144,8 @@ enum
Tag_RISCV_unaligned_access = 6,
Tag_RISCV_priv_spec = 8,
Tag_RISCV_priv_spec_minor = 10,
- Tag_RISCV_priv_spec_revision = 12
+ Tag_RISCV_priv_spec_revision = 12,
+ Tag_RISCV_x3_reg_usage = 16,
};
#endif /* _ELF_RISCV_H */
@@ -111,6 +111,8 @@ gld${EMULATION_NAME}_after_allocation (void)
bfd_elf${ELFSIZE}_riscv_set_data_segment_info (&link_info, (int *) phase);
ldelf_map_segments (need_layout);
+
+ bfd_elf${ELFSIZE}_riscv_update_x3_reg_usage (&link_info);
}
/* This is a convenient point to tell BFD about target specific flags.
@@ -7,3 +7,4 @@
Attribute Section: riscv
File Attributes
Tag_RISCV_arch: "rv32i2p1_a2p0"
+ Tag_RISCV_x3_reg_usage: reserved
@@ -7,3 +7,4 @@
Attribute Section: riscv
File Attributes
Tag_RISCV_arch: "rv32i2p1_a2p0"
+ Tag_RISCV_x3_reg_usage: reserved
@@ -7,3 +7,4 @@
Attribute Section: riscv
File Attributes
Tag_RISCV_arch: "rv32i2p1_a2p0_xbar2p0_xfoo2p0"
+ Tag_RISCV_x3_reg_usage: reserved
@@ -10,3 +10,4 @@ File Attributes
Tag_RISCV_priv_spec: 1
Tag_RISCV_priv_spec_minor: 9
Tag_RISCV_priv_spec_revision: 1
+ Tag_RISCV_x3_reg_usage: reserved
@@ -10,3 +10,4 @@ File Attributes
Tag_RISCV_priv_spec: 1
Tag_RISCV_priv_spec_minor: 9
Tag_RISCV_priv_spec_revision: 1
+ Tag_RISCV_x3_reg_usage: reserved
@@ -10,3 +10,4 @@ File Attributes
Tag_RISCV_priv_spec: 1
Tag_RISCV_priv_spec_minor: 9
Tag_RISCV_priv_spec_revision: 1
+ Tag_RISCV_x3_reg_usage: reserved
@@ -11,3 +11,4 @@ File Attributes
Tag_RISCV_arch: [a-zA-Z0-9_\"].*
Tag_RISCV_priv_spec: 1
Tag_RISCV_priv_spec_minor: 11
+ Tag_RISCV_x3_reg_usage: reserved
@@ -11,3 +11,4 @@ File Attributes
Tag_RISCV_arch: [a-zA-Z0-9_\"].*
Tag_RISCV_priv_spec: 1
Tag_RISCV_priv_spec_minor: 11
+ Tag_RISCV_x3_reg_usage: reserved
@@ -12,3 +12,4 @@ File Attributes
Tag_RISCV_arch: [a-zA-Z0-9_\"].*
Tag_RISCV_priv_spec: 1
Tag_RISCV_priv_spec_minor: 11
+ Tag_RISCV_x3_reg_usage: reserved
@@ -12,3 +12,4 @@ File Attributes
Tag_RISCV_arch: [a-zA-Z0-9_\"].*
Tag_RISCV_priv_spec: 1
Tag_RISCV_priv_spec_minor: 11
+ Tag_RISCV_x3_reg_usage: reserved
@@ -12,3 +12,4 @@ File Attributes
Tag_RISCV_arch: [a-zA-Z0-9_\"].*
Tag_RISCV_priv_spec: 1
Tag_RISCV_priv_spec_minor: 11
+ Tag_RISCV_x3_reg_usage: reserved
@@ -12,3 +12,4 @@ File Attributes
Tag_RISCV_arch: [a-zA-Z0-9_\"].*
Tag_RISCV_priv_spec: 1
Tag_RISCV_priv_spec_minor: 11
+ Tag_RISCV_x3_reg_usage: reserved
@@ -8,3 +8,4 @@ Attribute Section: riscv
File Attributes
Tag_RISCV_arch: [a-zA-Z0-9_\"].*
Tag_RISCV_unaligned_access: Unaligned access
+ Tag_RISCV_x3_reg_usage: reserved
@@ -8,3 +8,4 @@ Attribute Section: riscv
File Attributes
Tag_RISCV_arch: [a-zA-Z0-9_\"].*
Tag_RISCV_unaligned_access: Unaligned access
+ Tag_RISCV_x3_reg_usage: reserved
@@ -8,3 +8,4 @@ Attribute Section: riscv
File Attributes
Tag_RISCV_arch: [a-zA-Z0-9_\"].*
Tag_RISCV_unaligned_access: Unaligned access
+ Tag_RISCV_x3_reg_usage: reserved
@@ -7,3 +7,4 @@
Attribute Section: riscv
File Attributes
Tag_RISCV_arch: [a-zA-Z0-9_\"].*
+ Tag_RISCV_x3_reg_usage: reserved
@@ -8,3 +8,4 @@ Attribute Section: riscv
File Attributes
Tag_RISCV_arch: [a-zA-Z0-9_\"].*
Tag_RISCV_unaligned_access: Unaligned access
+ Tag_RISCV_x3_reg_usage: reserved
@@ -7,3 +7,4 @@
Attribute Section: riscv
File Attributes
Tag_RISCV_arch: "rv32i2p1_a2p1"
+ Tag_RISCV_x3_reg_usage: reserved
new file mode 100644
@@ -0,0 +1,11 @@
+.ifdef __relax__
+.attribute Tag_RISCV_x3_reg_usage, 1
+.endif
+
+.ifdef __reserved__
+.attribute Tag_RISCV_x3_reg_usage, 4
+.endif
+
+.ifdef __unknown__
+.attribute Tag_RISCV_x3_reg_usage, 5
+.endif
new file mode 100644
@@ -0,0 +1,12 @@
+ .text
+ .globl _start
+_start:
+ lla a0, x
+ lui a1, %hi(x)
+ addi a1, a1, %lo(x)
+
+ .data
+ .word 0x0
+ .globl x
+x:
+ .word 0x1
new file mode 100644
@@ -0,0 +1,14 @@
+#source: attr-merge-x3-reg-usage-code.s
+#source: attr-merge-x3-reg-usage-attrs.s
+#as:
+#ld:
+#objdump: -d -Mno-aliases
+
+.*:[ ]+file format .*
+
+
+Disassembly of section \.text:
+
+0+[0-9a-f]+ <_start>:
+.*:[ ]+[0-9a-f]+[ ]+addi[ ]+a0,gp,\-[0-9]+ # [0-9a-f]+ <x>
+.*:[ ]+[0-9a-f]+[ ]+addi[ ]+a1,gp,\-[0-9]+ # [0-9a-f]+ <x>
new file mode 100644
@@ -0,0 +1 @@
+.attribute Tag_RISCV_x3_reg_usage, 1
new file mode 100644
@@ -0,0 +1 @@
+.attribute Tag_RISCV_x3_reg_usage, 4
new file mode 100644
@@ -0,0 +1,5 @@
+#source: attr-merge-x3-reg-usage-fail-01.s
+#source: attr-merge-x3-reg-usage-fail-02.s
+#as:
+#ld:
+#error: .*use Tag_RISCV_x3_reg_usage \(4\) but output use Tag_RISCV_x3_reg_usage \(1\)
new file mode 100644
@@ -0,0 +1,14 @@
+#source: attr-merge-x3-reg-usage-code.s
+#source: attr-merge-x3-reg-usage-attrs.s
+#as: --defsym __relax__=1
+#ld:
+#objdump: -d -Mno-aliases
+
+.*:[ ]+file format .*
+
+
+Disassembly of section \.text:
+
+0+[0-9a-f]+ <_start>:
+.*:[ ]+[0-9a-f]+[ ]+addi[ ]+a0,gp,\-[0-9]+ # [0-9a-f]+ <x>
+.*:[ ]+[0-9a-f]+[ ]+addi[ ]+a1,gp,\-[0-9]+ # [0-9a-f]+ <x>
new file mode 100644
@@ -0,0 +1,16 @@
+#source: attr-merge-x3-reg-usage-code.s
+#source: attr-merge-x3-reg-usage-attrs.s
+#as: --defsym __reserved__=1
+#ld:
+#objdump: -d -Mno-aliases
+
+.*:[ ]+file format .*
+
+
+Disassembly of section \.text:
+
+0+[0-9a-f]+ <_start>:
+.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+a0,0x[0-9a-f]+
+.*:[ ]+[0-9a-f]+[ ]+addi[ ]+a0,a0,[0-9]+ # [0-9a-f]+ <x>
+.*:[ ]+[0-9a-f]+[ ]+lui[ ]+a1,0x[0-9a-f]+
+.*:[ ]+[0-9a-f]+[ ]+addi[ ]+a1,a1,[0-9]+ # [0-9a-f]+ <x>
new file mode 100644
@@ -0,0 +1,15 @@
+#source: attr-merge-x3-reg-usage-code.s
+#source: attr-merge-x3-reg-usage-attrs.s
+#as: --defsym __unknown__=1
+#ld:
+#objdump: -d -Mno-aliases
+#warning: .*unknown value for Tag_RISCV_x3_reg_usage.*
+
+.*:[ ]+file format .*
+
+
+Disassembly of section \.text:
+
+0+[0-9a-f]+ <_start>:
+.*:[ ]+[0-9a-f]+[ ]+addi[ ]+a0,gp,\-[0-9]+ # [0-9a-f]+ <x>
+.*:[ ]+[0-9a-f]+[ ]+addi[ ]+a1,gp,\-[0-9]+ # [0-9a-f]+ <x>
@@ -170,6 +170,11 @@ if [istarget "riscv*-*-*"] {
run_dump_test "attr-merge-priv-spec-failed-04"
run_dump_test "attr-merge-priv-spec-failed-05"
run_dump_test "attr-merge-priv-spec-failed-06"
+ run_dump_test "attr-merge-x3-reg-usage-default"
+ run_dump_test "attr-merge-x3-reg-usage-relax"
+ run_dump_test "attr-merge-x3-reg-usage-reserved"
+ run_dump_test "attr-merge-x3-reg-usage-unknown"
+ run_dump_test "attr-merge-x3-reg-usage-fail"
run_dump_test "attr-phdr"
run_dump_test "relax-max-align-gp"
run_dump_test "uleb128"