@@ -1804,7 +1804,8 @@ perform_relocation (const reloc_howto_type *howto,
break;
case R_RISCV_LO12_I:
- case R_RISCV_GPREL_I:
+ case R_RISCV_LUI_GPREL_I:
+ case R_RISCV_AUIPC_GPREL_I:
case R_RISCV_TPREL_LO12_I:
case R_RISCV_TPREL_I:
case R_RISCV_PCREL_LO12_I:
@@ -1814,7 +1815,8 @@ perform_relocation (const reloc_howto_type *howto,
break;
case R_RISCV_LO12_S:
- case R_RISCV_GPREL_S:
+ case R_RISCV_LUI_GPREL_S:
+ case R_RISCV_AUIPC_GPREL_S:
case R_RISCV_TPREL_LO12_S:
case R_RISCV_TPREL_S:
case R_RISCV_PCREL_LO12_S:
@@ -2816,8 +2818,10 @@ riscv_elf_relocate_section (bfd *output_bfd,
r = bfd_reloc_overflow;
break;
- case R_RISCV_GPREL_I:
- case R_RISCV_GPREL_S:
+ case R_RISCV_LUI_GPREL_I:
+ case R_RISCV_LUI_GPREL_S:
+ case R_RISCV_AUIPC_GPREL_I:
+ case R_RISCV_AUIPC_GPREL_S:
{
bfd_vma gp = riscv_global_pointer_value (info);
bool x0_base = VALID_ITYPE_IMM (relocation + rel->r_addend);
@@ -3136,6 +3140,14 @@ riscv_elf_relocate_section (bfd *output_bfd,
switch (r)
{
case bfd_reloc_ok:
+ {
+ /* Shouldn't emit internal relocs. */
+ reloc_howto_type *emit_howto =
+ riscv_emit_internal_reloc_type_lookup (input_bfd, r_type);
+ if (emit_howto)
+ rel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info),
+ emit_howto->type);
+ }
continue;
case bfd_reloc_overflow:
@@ -4772,11 +4784,11 @@ _bfd_riscv_relax_lui (bfd *abfd,
switch (ELFNN_R_TYPE (rel->r_info))
{
case R_RISCV_LO12_I:
- rel->r_info = ELFNN_R_INFO (sym, R_RISCV_GPREL_I);
+ rel->r_info = ELFNN_R_INFO (sym, R_RISCV_LUI_GPREL_I);
return true;
case R_RISCV_LO12_S:
- rel->r_info = ELFNN_R_INFO (sym, R_RISCV_GPREL_S);
+ rel->r_info = ELFNN_R_INFO (sym, R_RISCV_LUI_GPREL_S);
return true;
case R_RISCV_HI20:
@@ -5036,12 +5048,12 @@ _bfd_riscv_relax_pc (bfd *abfd ATTRIBUTE_UNUSED,
switch (ELFNN_R_TYPE (rel->r_info))
{
case R_RISCV_PCREL_LO12_I:
- rel->r_info = ELFNN_R_INFO (sym, R_RISCV_GPREL_I);
+ rel->r_info = ELFNN_R_INFO (sym, R_RISCV_AUIPC_GPREL_I);
rel->r_addend += hi_reloc.hi_addend;
return true;
case R_RISCV_PCREL_LO12_S:
- rel->r_info = ELFNN_R_INFO (sym, R_RISCV_GPREL_S);
+ rel->r_info = ELFNN_R_INFO (sym, R_RISCV_AUIPC_GPREL_S);
rel->r_addend += hi_reloc.hi_addend;
return true;
@@ -884,7 +884,7 @@ static reloc_howto_type howto_table_internal[] =
/* R_RISCV_DELETE. */
EMPTY_HOWTO (0),
- /* High 6 bits of 18-bit absolute address. */
+ /* For lui relaxation, high 6 bits of 18-bit absolute address. */
HOWTO (R_RISCV_RVC_LUI, /* type */
0, /* rightshift */
2, /* size */
@@ -899,8 +899,8 @@ static reloc_howto_type howto_table_internal[] =
ENCODE_CITYPE_IMM (-1U), /* dst_mask */
false), /* pcrel_offset */
- /* GP-relative load. */
- HOWTO (R_RISCV_GPREL_I, /* type */
+ /* For lui relaxation, GP-relative load. */
+ HOWTO (R_RISCV_LUI_GPREL_I, /* type */
0, /* rightshift */
4, /* size */
32, /* bitsize */
@@ -908,14 +908,14 @@ static reloc_howto_type howto_table_internal[] =
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
- "R_RISCV_GPREL_I", /* name */
+ "R_RISCV_LUI_GPREL_I", /* name */
false, /* partial_inplace */
0, /* src_mask */
ENCODE_ITYPE_IMM (-1U), /* dst_mask */
false), /* pcrel_offset */
- /* GP-relative store. */
- HOWTO (R_RISCV_GPREL_S, /* type */
+ /* For lui relaxation, GP-relative store. */
+ HOWTO (R_RISCV_LUI_GPREL_S, /* type */
0, /* rightshift */
4, /* size */
32, /* bitsize */
@@ -923,13 +923,43 @@ static reloc_howto_type howto_table_internal[] =
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
- "R_RISCV_GPREL_S", /* name */
+ "R_RISCV_LUI_GPREL_S", /* name */
false, /* partial_inplace */
0, /* src_mask */
ENCODE_STYPE_IMM (-1U), /* dst_mask */
false), /* pcrel_offset */
- /* TP-relative TLS LE load. */
+ /* For auipc relaxation, GP-relative load. */
+ HOWTO (R_RISCV_AUIPC_GPREL_I, /* type */
+ 0, /* rightshift */
+ 4, /* size */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_RISCV_AUIPC_GPREL_I", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ ENCODE_ITYPE_IMM (-1U), /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* For auipc relaxation, GP-relative store. */
+ HOWTO (R_RISCV_AUIPC_GPREL_S, /* type */
+ 0, /* rightshift */
+ 4, /* size */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_RISCV_AUIPC_GPREL_S", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ ENCODE_STYPE_IMM (-1U), /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* For tprel relaxation, TP-relative TLS LE load. */
HOWTO (R_RISCV_TPREL_I, /* type */
0, /* rightshift */
4, /* size */
@@ -944,7 +974,7 @@ static reloc_howto_type howto_table_internal[] =
ENCODE_ITYPE_IMM (-1U), /* dst_mask */
false), /* pcrel_offset */
- /* TP-relative TLS LE store. */
+ /* For tprel relaxation, TP-relative TLS LE store. */
HOWTO (R_RISCV_TPREL_S, /* type */
0, /* rightshift */
4, /* size */
@@ -1038,6 +1068,42 @@ riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
return NULL;
}
+/* A mapping from RISC-V internal reloc types to standard reloc types. */
+struct elf_internal_reloc_map
+{
+ enum elf_riscv_reloc_type internal;
+ enum elf_riscv_reloc_type standard;
+};
+
+static const struct elf_internal_reloc_map riscv_internal_reloc_map[] =
+{
+ { R_RISCV_DELETE, R_RISCV_NONE },
+ { R_RISCV_RVC_LUI, R_RISCV_HI20 },
+ { R_RISCV_LUI_GPREL_I, R_RISCV_LO12_I},
+ { R_RISCV_LUI_GPREL_S, R_RISCV_LO12_S},
+ { R_RISCV_AUIPC_GPREL_I, R_RISCV_PCREL_LO12_I},
+ { R_RISCV_AUIPC_GPREL_S, R_RISCV_PCREL_LO12_S},
+ { R_RISCV_TPREL_I, R_RISCV_TPREL_LO12_I },
+ { R_RISCV_TPREL_S, R_RISCV_TPREL_LO12_S },
+};
+
+reloc_howto_type *
+riscv_emit_internal_reloc_type_lookup (bfd *abfd, unsigned int r_type)
+{
+ if (r_type < ARRAY_SIZE (howto_table))
+ return NULL;
+
+ unsigned int i;
+ for (i = 0; i < ARRAY_SIZE (riscv_internal_reloc_map); i++)
+ if (riscv_internal_reloc_map[i].internal == r_type)
+ return &howto_table[riscv_internal_reloc_map[i].standard];
+
+ (*_bfd_error_handler)
+ (_("%pB: warning: mismatched internal relocation type %#x"),
+ abfd, r_type);
+ return NULL;
+}
+
reloc_howto_type *
riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
{
@@ -46,6 +46,9 @@ riscv_reloc_name_lookup (bfd *, const char *);
extern reloc_howto_type *
riscv_reloc_type_lookup (bfd *, bfd_reloc_code_real_type);
+extern reloc_howto_type *
+riscv_emit_internal_reloc_type_lookup (bfd *, unsigned int r_type);
+
extern reloc_howto_type *
riscv_elf_rtype_to_howto (bfd *, unsigned int r_type);
@@ -100,10 +100,12 @@ END_RELOC_NUMBERS (R_RISCV_max)
/* Internal relocations used exclusively by the relaxation pass. */
#define R_RISCV_DELETE (R_RISCV_max)
#define R_RISCV_RVC_LUI (R_RISCV_max + 1)
-#define R_RISCV_GPREL_I (R_RISCV_max + 2)
-#define R_RISCV_GPREL_S (R_RISCV_max + 3)
-#define R_RISCV_TPREL_I (R_RISCV_max + 4)
-#define R_RISCV_TPREL_S (R_RISCV_max + 5)
+#define R_RISCV_LUI_GPREL_I (R_RISCV_max + 2)
+#define R_RISCV_LUI_GPREL_S (R_RISCV_max + 3)
+#define R_RISCV_AUIPC_GPREL_I (R_RISCV_max + 4)
+#define R_RISCV_AUIPC_GPREL_S (R_RISCV_max + 5)
+#define R_RISCV_TPREL_I (R_RISCV_max + 6)
+#define R_RISCV_TPREL_S (R_RISCV_max + 7)
/* Processor specific flags for the ELF header e_flags field. */
new file mode 100644
@@ -0,0 +1,23 @@
+#name: c.lui to c.li relaxation
+#source: c-lui-2.s
+#as: -march=rv32ic
+#ld: -m[riscv_choose_ilp32_emul] -Tc-lui-2.ld --emit-relocs
+#objdump: -dr -M no-aliases,numeric
+
+.*: file format .*
+
+
+Disassembly of section \.text:
+
+.* <_start>:
+.*: 4501 c.li x10,0
+.*:[ ]+R_RISCV_HI20[ ]+foo
+.*: 7fe00513 addi x10,x0,2046
+.*:[ ]+R_RISCV_NONE[ ]+\*ABS\*\+0x2
+.*:[ ]+R_RISCV_LO12_I[ ]+foo
+.*:[ ]+R_RISCV_RELAX[ ]+\*ABS\*
+ ...
+
+.* <foo>:
+.*: 8082 c.jr x1
+#pass
@@ -123,9 +123,11 @@ if [istarget "riscv*-*-*"] {
run_dump_test "call-relax"
run_dump_test "pcgp-relax-01"
run_dump_test "pcgp-relax-01-norelaxgp"
+ run_dump_test "pcgp-relax-01-emitrelocs"
run_dump_test "pcgp-relax-02"
run_dump_test "c-lui"
run_dump_test "c-lui-2"
+ run_dump_test "c-lui-2-emitrelocs"
run_dump_test "disas-jalr"
run_dump_test "pcrel-lo-addend"
run_dump_test "pcrel-lo-addend-2a"
new file mode 100644
@@ -0,0 +1,38 @@
+#source: pcgp-relax-01.s
+#ld: --relax --emit-relocs
+#objdump: -dr -Mno-aliases
+
+.*:[ ]+file format .*
+
+
+Disassembly of section .text:
+
+0+[0-9a-f]+ <_start>:
+[ ]+[0-9a-f]+:[ ]+[0-9a-f]+[ ]+addi[ ]+a0,a0,[0-9]+
+[ ]+[0-9a-f]+:[ ]+R_RISCV_PCREL_LO12_I[ ]+.L2
+[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\*
+[ ]+[0-9a-f]+:[ ]+[0-9a-f]+[ ]+jal[ ]+ra,[0-9a-f]+ <_start>
+[ ]+[0-9a-f]+:[ ]+R_RISCV_JAL[ ]+_start
+[ ]+[0-9a-f]+:[ ]+[0-9a-f]+[ ]+addi[ ]+a1,gp,\-[0-9]+ # [0-9a-f]+ <data_g>
+[ ]+[0-9a-f]+:[ ]+R_RISCV_NONE[ ]+\*ABS\*\+0x4
+[ ]+[0-9a-f]+:[ ]+R_RISCV_NONE[ ]+\*ABS\*\+0x4
+[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\*
+[ ]+[0-9a-f]+:[ ]+R_RISCV_PCREL_LO12_I[ ]+data_g\-0x[0-9a-f]+
+[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\*
+[ ]+[0-9a-f]+:[ ]+[0-9a-f]+[ ]+addi[ ]+a2,gp,\-[0-9]+ # [0-9a-f]+ <data_g>
+[ ]+[0-9a-f]+:[ ]+R_RISCV_NONE[ ]+\*ABS\*\+0x4
+[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\*
+[ ]+[0-9a-f]+:[ ]+R_RISCV_LO12_I[ ]+data_g\-0x[0-9a-f]+
+[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\*
+[ ]+[0-9a-f]+:[ ]+[0-9a-f]+[ ]+addi[ ]+a3,tp,0 # 0 <data_t>
+[ ]+[0-9a-f]+:[ ]+R_RISCV_NONE[ ]+\*ABS\*\+0x4
+[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\*
+[ ]+[0-9a-f]+:[ ]+R_RISCV_NONE[ ]+\*ABS\*\+0x4
+[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\*
+[ ]+[0-9a-f]+:[ ]+R_RISCV_TPREL_LO12_I[ ]+data_t
+[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\*
+
+0+[0-9a-f]+ <.L2>:
+[ ]+[0-9a-f]+:[ ]+[0-9a-f]+[ ]+auipc[ ]+a0,0x[0-9a-f]+
+[ ]+[0-9a-f]+:[ ]+R_RISCV_PCREL_HI20[ ]+data_g
+[ ]+[0-9a-f]+:[ ]+R_RISCV_RELAX[ ]+\*ABS\*