mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-24 20:28:28 +08:00
Rework RISC-V relocations
Before this commit we didn't cleanly support CFI directives because the internal offsets used to get relaxed which broke them. This patch significantly reworks how we handle linker relaxations: * DWARF is now properly supported * There is a ".option norelax" to disable relaxations, for when users write assembly that can't be relaxed (if it's to be later patched up, for example). * There is an additional _RELAX relocation that specifies when previous relocations can be relaxed. We're in the process of documenting the RISC-V ELF ABI, which will include documentation of our relocations https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md but we expect that this relocation set will remain ABI compatible in the future (ie, it's safe to release). Thanks to Kuan-Lin Chen for figuring out how to correctly relax the debug info! include/ * elf/riscv.h: Add R_RISCV_TPREL_I through R_RISCV_SET32. bfd/ * reloc.c (BFD_RELOC_RISCV_TPREL_I): New relocation. (BFD_RELOC_RISCV_TPREL_S): Likewise. (BFD_RELOC_RISCV_RELAX): Likewise. (BFD_RELOC_RISCV_CFA): Likewise. (BFD_RELOC_RISCV_SUB6): Likewise. (BFD_RELOC_RISCV_SET8): Likewise. (BFD_RELOC_RISCV_SET8): Likewise. (BFD_RELOC_RISCV_SET16): Likewise. (BFD_RELOC_RISCV_SET32): Likewise. * elfnn-riscv.c (perform_relocation): Handle the new relocations. (_bfd_riscv_relax_tls_le): Likewise. (_bfd_riscv_relax_align): Likewise. (_bfd_riscv_relax_section): Likewise. (howto_table): Likewise. (riscv_reloc_map): Likewise. (relax_func_t): New type. (_bfd_riscv_relax_call): Add reserve_size argument, which controls the maximal offset pessimism. Correct type of max_alignment. (_bfd_riscv_relax_lui): Likewise. (_bfd_riscv_relax_tls_le): Likewise. (_bfd_riscv_relax_align): Likewise. (_bfd_riscv_relax_section): Compute the required reserve size when relocating and use it to when calling relax_func. * bfd-in2.h: Regenerate. * libbfd.h: Likewise. gas/ * config/tc-riscv.c (riscv_set_options): Add relax. (riscv_opts): Likewise. (s_riscv_option): Add relax and norelax. (riscv_apply_const_reloc): New function. (append_insn): Move constant relocation handling to riscv_apply_const_reloc. (md_pcrel_from): Likewise. (parse_relocation): Skip BFD_RELOC_UNUSED. (md_pcrel_from): Handle BFD_RELOC_RISCV_SUB6, BFD_RELOC_RISCV_RELAX, BFD_RELOC_RISCV_CFA. (md_apply_fix): Likewise. (riscv_pre_output_hook): New function. * config/tc-riscv.h (md_pre_output_hook): Define. (riscv_pre_output_hook): Declare. (DWARF_CIE_DATA_ALIGNMENT): Always -4.
This commit is contained in:

committed by
Alan Modra

parent
1d65abb5e2
commit
45f764234a
@ -1,3 +1,33 @@
|
|||||||
|
2016-12-20 Andrew Waterman <andrew@sifive.com>
|
||||||
|
Kuan-Lin Chen <kuanlinchentw@gmail.com>
|
||||||
|
|
||||||
|
* reloc.c (BFD_RELOC_RISCV_TPREL_I): New relocation.
|
||||||
|
(BFD_RELOC_RISCV_TPREL_S): Likewise.
|
||||||
|
(BFD_RELOC_RISCV_RELAX): Likewise.
|
||||||
|
(BFD_RELOC_RISCV_CFA): Likewise.
|
||||||
|
(BFD_RELOC_RISCV_SUB6): Likewise.
|
||||||
|
(BFD_RELOC_RISCV_SET8): Likewise.
|
||||||
|
(BFD_RELOC_RISCV_SET8): Likewise.
|
||||||
|
(BFD_RELOC_RISCV_SET16): Likewise.
|
||||||
|
(BFD_RELOC_RISCV_SET32): Likewise.
|
||||||
|
* elfnn-riscv.c (perform_relocation): Handle the new
|
||||||
|
relocations.
|
||||||
|
(_bfd_riscv_relax_tls_le): Likewise.
|
||||||
|
(_bfd_riscv_relax_align): Likewise.
|
||||||
|
(_bfd_riscv_relax_section): Likewise.
|
||||||
|
(howto_table): Likewise.
|
||||||
|
(riscv_reloc_map): Likewise.
|
||||||
|
(relax_func_t): New type.
|
||||||
|
(_bfd_riscv_relax_call): Add reserve_size argument, which
|
||||||
|
controls the maximal offset pessimism. Correct type of max_alignment.
|
||||||
|
(_bfd_riscv_relax_lui): Likewise.
|
||||||
|
(_bfd_riscv_relax_tls_le): Likewise.
|
||||||
|
(_bfd_riscv_relax_align): Likewise.
|
||||||
|
(_bfd_riscv_relax_section): Compute the required reserve size
|
||||||
|
when relocating and use it to when calling relax_func.
|
||||||
|
* bfd-in2.h: Regenerate.
|
||||||
|
* libbfd.h: Likewise.
|
||||||
|
|
||||||
2016-12-20 Andrew Waterman <andrew@sifive.com>
|
2016-12-20 Andrew Waterman <andrew@sifive.com>
|
||||||
|
|
||||||
* elfnn-riscv.c: Formatting and comment fixes throughout.
|
* elfnn-riscv.c: Formatting and comment fixes throughout.
|
||||||
|
@ -4737,6 +4737,15 @@ number for the SBIC, SBIS, SBI and CBI instructions */
|
|||||||
BFD_RELOC_RISCV_RVC_LUI,
|
BFD_RELOC_RISCV_RVC_LUI,
|
||||||
BFD_RELOC_RISCV_GPREL_I,
|
BFD_RELOC_RISCV_GPREL_I,
|
||||||
BFD_RELOC_RISCV_GPREL_S,
|
BFD_RELOC_RISCV_GPREL_S,
|
||||||
|
BFD_RELOC_RISCV_TPREL_I,
|
||||||
|
BFD_RELOC_RISCV_TPREL_S,
|
||||||
|
BFD_RELOC_RISCV_RELAX,
|
||||||
|
BFD_RELOC_RISCV_CFA,
|
||||||
|
BFD_RELOC_RISCV_SUB6,
|
||||||
|
BFD_RELOC_RISCV_SET6,
|
||||||
|
BFD_RELOC_RISCV_SET8,
|
||||||
|
BFD_RELOC_RISCV_SET16,
|
||||||
|
BFD_RELOC_RISCV_SET32,
|
||||||
|
|
||||||
/* Renesas RL78 Relocations. */
|
/* Renesas RL78 Relocations. */
|
||||||
BFD_RELOC_RL78_NEG8,
|
BFD_RELOC_RL78_NEG8,
|
||||||
|
@ -1493,6 +1493,7 @@ perform_relocation (const reloc_howto_type *howto,
|
|||||||
case R_RISCV_LO12_I:
|
case R_RISCV_LO12_I:
|
||||||
case R_RISCV_GPREL_I:
|
case R_RISCV_GPREL_I:
|
||||||
case R_RISCV_TPREL_LO12_I:
|
case R_RISCV_TPREL_LO12_I:
|
||||||
|
case R_RISCV_TPREL_I:
|
||||||
case R_RISCV_PCREL_LO12_I:
|
case R_RISCV_PCREL_LO12_I:
|
||||||
value = ENCODE_ITYPE_IMM (value);
|
value = ENCODE_ITYPE_IMM (value);
|
||||||
break;
|
break;
|
||||||
@ -1500,6 +1501,7 @@ perform_relocation (const reloc_howto_type *howto,
|
|||||||
case R_RISCV_LO12_S:
|
case R_RISCV_LO12_S:
|
||||||
case R_RISCV_GPREL_S:
|
case R_RISCV_GPREL_S:
|
||||||
case R_RISCV_TPREL_LO12_S:
|
case R_RISCV_TPREL_LO12_S:
|
||||||
|
case R_RISCV_TPREL_S:
|
||||||
case R_RISCV_PCREL_LO12_S:
|
case R_RISCV_PCREL_LO12_S:
|
||||||
value = ENCODE_STYPE_IMM (value);
|
value = ENCODE_STYPE_IMM (value);
|
||||||
break;
|
break;
|
||||||
@ -1548,10 +1550,15 @@ perform_relocation (const reloc_howto_type *howto,
|
|||||||
case R_RISCV_ADD16:
|
case R_RISCV_ADD16:
|
||||||
case R_RISCV_ADD32:
|
case R_RISCV_ADD32:
|
||||||
case R_RISCV_ADD64:
|
case R_RISCV_ADD64:
|
||||||
|
case R_RISCV_SUB6:
|
||||||
case R_RISCV_SUB8:
|
case R_RISCV_SUB8:
|
||||||
case R_RISCV_SUB16:
|
case R_RISCV_SUB16:
|
||||||
case R_RISCV_SUB32:
|
case R_RISCV_SUB32:
|
||||||
case R_RISCV_SUB64:
|
case R_RISCV_SUB64:
|
||||||
|
case R_RISCV_SET6:
|
||||||
|
case R_RISCV_SET8:
|
||||||
|
case R_RISCV_SET16:
|
||||||
|
case R_RISCV_SET32:
|
||||||
case R_RISCV_TLS_DTPREL32:
|
case R_RISCV_TLS_DTPREL32:
|
||||||
case R_RISCV_TLS_DTPREL64:
|
case R_RISCV_TLS_DTPREL64:
|
||||||
break;
|
break;
|
||||||
@ -1817,6 +1824,7 @@ riscv_elf_relocate_section (bfd *output_bfd,
|
|||||||
switch (r_type)
|
switch (r_type)
|
||||||
{
|
{
|
||||||
case R_RISCV_NONE:
|
case R_RISCV_NONE:
|
||||||
|
case R_RISCV_RELAX:
|
||||||
case R_RISCV_TPREL_ADD:
|
case R_RISCV_TPREL_ADD:
|
||||||
case R_RISCV_COPY:
|
case R_RISCV_COPY:
|
||||||
case R_RISCV_JUMP_SLOT:
|
case R_RISCV_JUMP_SLOT:
|
||||||
@ -1830,6 +1838,10 @@ riscv_elf_relocate_section (bfd *output_bfd,
|
|||||||
case R_RISCV_RVC_LUI:
|
case R_RISCV_RVC_LUI:
|
||||||
case R_RISCV_LO12_I:
|
case R_RISCV_LO12_I:
|
||||||
case R_RISCV_LO12_S:
|
case R_RISCV_LO12_S:
|
||||||
|
case R_RISCV_SET6:
|
||||||
|
case R_RISCV_SET8:
|
||||||
|
case R_RISCV_SET16:
|
||||||
|
case R_RISCV_SET32:
|
||||||
/* These require no special handling beyond perform_relocation. */
|
/* These require no special handling beyond perform_relocation. */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1923,6 +1935,7 @@ riscv_elf_relocate_section (bfd *output_bfd,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case R_RISCV_SUB6:
|
||||||
case R_RISCV_SUB8:
|
case R_RISCV_SUB8:
|
||||||
case R_RISCV_SUB16:
|
case R_RISCV_SUB16:
|
||||||
case R_RISCV_SUB32:
|
case R_RISCV_SUB32:
|
||||||
@ -1952,6 +1965,11 @@ riscv_elf_relocate_section (bfd *output_bfd,
|
|||||||
|
|
||||||
case R_RISCV_TPREL_LO12_I:
|
case R_RISCV_TPREL_LO12_I:
|
||||||
case R_RISCV_TPREL_LO12_S:
|
case R_RISCV_TPREL_LO12_S:
|
||||||
|
relocation = tpoff (info, relocation);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case R_RISCV_TPREL_I:
|
||||||
|
case R_RISCV_TPREL_S:
|
||||||
relocation = tpoff (info, relocation);
|
relocation = tpoff (info, relocation);
|
||||||
if (VALID_ITYPE_IMM (relocation + rel->r_addend))
|
if (VALID_ITYPE_IMM (relocation + rel->r_addend))
|
||||||
{
|
{
|
||||||
@ -1961,6 +1979,8 @@ riscv_elf_relocate_section (bfd *output_bfd,
|
|||||||
insn |= X_TP << OP_SH_RS1;
|
insn |= X_TP << OP_SH_RS1;
|
||||||
bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
|
bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
r = bfd_reloc_overflow;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RISCV_GPREL_I:
|
case R_RISCV_GPREL_I:
|
||||||
@ -2668,6 +2688,11 @@ riscv_relax_delete_bytes (bfd *abfd, asection *sec, bfd_vma addr, size_t count)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef bfd_boolean (*relax_func_t) (bfd *, asection *, asection *,
|
||||||
|
struct bfd_link_info *,
|
||||||
|
Elf_Internal_Rela *,
|
||||||
|
bfd_vma, bfd_vma, bfd_vma, bfd_boolean *);
|
||||||
|
|
||||||
/* Relax AUIPC + JALR into JAL. */
|
/* Relax AUIPC + JALR into JAL. */
|
||||||
|
|
||||||
static bfd_boolean
|
static bfd_boolean
|
||||||
@ -2675,7 +2700,8 @@ _bfd_riscv_relax_call (bfd *abfd, asection *sec, asection *sym_sec,
|
|||||||
struct bfd_link_info *link_info,
|
struct bfd_link_info *link_info,
|
||||||
Elf_Internal_Rela *rel,
|
Elf_Internal_Rela *rel,
|
||||||
bfd_vma symval,
|
bfd_vma symval,
|
||||||
unsigned int max_alignment,
|
bfd_vma max_alignment,
|
||||||
|
bfd_vma reserve_size ATTRIBUTE_UNUSED,
|
||||||
bfd_boolean *again)
|
bfd_boolean *again)
|
||||||
{
|
{
|
||||||
bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
|
bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
|
||||||
@ -2757,7 +2783,8 @@ _bfd_riscv_relax_lui (bfd *abfd,
|
|||||||
struct bfd_link_info *link_info,
|
struct bfd_link_info *link_info,
|
||||||
Elf_Internal_Rela *rel,
|
Elf_Internal_Rela *rel,
|
||||||
bfd_vma symval,
|
bfd_vma symval,
|
||||||
unsigned int max_alignment,
|
bfd_vma max_alignment,
|
||||||
|
bfd_vma reserve_size,
|
||||||
bfd_boolean *again)
|
bfd_boolean *again)
|
||||||
{
|
{
|
||||||
bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
|
bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
|
||||||
@ -2773,8 +2800,10 @@ _bfd_riscv_relax_lui (bfd *abfd,
|
|||||||
/* Is the reference in range of x0 or gp?
|
/* Is the reference in range of x0 or gp?
|
||||||
Valid gp range conservatively because of alignment issue. */
|
Valid gp range conservatively because of alignment issue. */
|
||||||
if (VALID_ITYPE_IMM (symval)
|
if (VALID_ITYPE_IMM (symval)
|
||||||
|| (symval >= gp && VALID_ITYPE_IMM (symval - gp + max_alignment))
|
|| (symval >= gp
|
||||||
|| (symval < gp && VALID_ITYPE_IMM (symval - gp - max_alignment)))
|
&& VALID_ITYPE_IMM (symval - gp + max_alignment + reserve_size))
|
||||||
|
|| (symval < gp
|
||||||
|
&& VALID_ITYPE_IMM (symval - gp - max_alignment - reserve_size)))
|
||||||
{
|
{
|
||||||
unsigned sym = ELFNN_R_SYM (rel->r_info);
|
unsigned sym = ELFNN_R_SYM (rel->r_info);
|
||||||
switch (ELFNN_R_TYPE (rel->r_info))
|
switch (ELFNN_R_TYPE (rel->r_info))
|
||||||
@ -2832,20 +2861,35 @@ _bfd_riscv_relax_tls_le (bfd *abfd,
|
|||||||
struct bfd_link_info *link_info,
|
struct bfd_link_info *link_info,
|
||||||
Elf_Internal_Rela *rel,
|
Elf_Internal_Rela *rel,
|
||||||
bfd_vma symval,
|
bfd_vma symval,
|
||||||
unsigned int max_alignment ATTRIBUTE_UNUSED,
|
bfd_vma max_alignment ATTRIBUTE_UNUSED,
|
||||||
|
bfd_vma reserve_size ATTRIBUTE_UNUSED,
|
||||||
bfd_boolean *again)
|
bfd_boolean *again)
|
||||||
{
|
{
|
||||||
/* See if this symbol is in range of tp. */
|
/* See if this symbol is in range of tp. */
|
||||||
if (RISCV_CONST_HIGH_PART (tpoff (link_info, symval)) != 0)
|
if (RISCV_CONST_HIGH_PART (tpoff (link_info, symval)) != 0)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* We can delete the unnecessary LUI and tp add. The LO12 reloc will be
|
|
||||||
made directly tp-relative. */
|
|
||||||
BFD_ASSERT (rel->r_offset + 4 <= sec->size);
|
BFD_ASSERT (rel->r_offset + 4 <= sec->size);
|
||||||
rel->r_info = ELFNN_R_INFO (0, R_RISCV_NONE);
|
switch (ELFNN_R_TYPE (rel->r_info))
|
||||||
|
{
|
||||||
|
case R_RISCV_TPREL_LO12_I:
|
||||||
|
rel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info), R_RISCV_TPREL_I);
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
*again = TRUE;
|
case R_RISCV_TPREL_LO12_S:
|
||||||
return riscv_relax_delete_bytes (abfd, sec, rel->r_offset, 4);
|
rel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info), R_RISCV_TPREL_S);
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case R_RISCV_TPREL_HI20:
|
||||||
|
case R_RISCV_TPREL_ADD:
|
||||||
|
/* We can delete the unnecessary instruction and reloc. */
|
||||||
|
rel->r_info = ELFNN_R_INFO (0, R_RISCV_NONE);
|
||||||
|
*again = TRUE;
|
||||||
|
return riscv_relax_delete_bytes (abfd, sec, rel->r_offset, 4);
|
||||||
|
|
||||||
|
default:
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Implement R_RISCV_ALIGN by deleting excess alignment NOPs. */
|
/* Implement R_RISCV_ALIGN by deleting excess alignment NOPs. */
|
||||||
@ -2856,7 +2900,8 @@ _bfd_riscv_relax_align (bfd *abfd, asection *sec,
|
|||||||
struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
|
struct bfd_link_info *link_info ATTRIBUTE_UNUSED,
|
||||||
Elf_Internal_Rela *rel,
|
Elf_Internal_Rela *rel,
|
||||||
bfd_vma symval,
|
bfd_vma symval,
|
||||||
unsigned int max_alignment ATTRIBUTE_UNUSED,
|
bfd_vma max_alignment ATTRIBUTE_UNUSED,
|
||||||
|
bfd_vma reserve_size ATTRIBUTE_UNUSED,
|
||||||
bfd_boolean *again ATTRIBUTE_UNUSED)
|
bfd_boolean *again ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
|
bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
|
||||||
@ -2909,7 +2954,7 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
|
|||||||
Elf_Internal_Rela *relocs;
|
Elf_Internal_Rela *relocs;
|
||||||
bfd_boolean ret = FALSE;
|
bfd_boolean ret = FALSE;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
unsigned int max_alignment;
|
bfd_vma max_alignment, reserve_size = 0;
|
||||||
|
|
||||||
*again = FALSE;
|
*again = FALSE;
|
||||||
|
|
||||||
@ -2935,7 +2980,7 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
|
|||||||
{
|
{
|
||||||
asection *sym_sec;
|
asection *sym_sec;
|
||||||
Elf_Internal_Rela *rel = relocs + i;
|
Elf_Internal_Rela *rel = relocs + i;
|
||||||
typeof (&_bfd_riscv_relax_call) relax_func = NULL;
|
relax_func_t relax_func;
|
||||||
int type = ELFNN_R_TYPE (rel->r_info);
|
int type = ELFNN_R_TYPE (rel->r_info);
|
||||||
bfd_vma symval;
|
bfd_vma symval;
|
||||||
|
|
||||||
@ -2947,13 +2992,26 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
|
|||||||
|| type == R_RISCV_LO12_I
|
|| type == R_RISCV_LO12_I
|
||||||
|| type == R_RISCV_LO12_S)
|
|| type == R_RISCV_LO12_S)
|
||||||
relax_func = _bfd_riscv_relax_lui;
|
relax_func = _bfd_riscv_relax_lui;
|
||||||
else if (type == R_RISCV_TPREL_HI20 || type == R_RISCV_TPREL_ADD)
|
else if (type == R_RISCV_TPREL_HI20
|
||||||
|
|| type == R_RISCV_TPREL_ADD
|
||||||
|
|| type == R_RISCV_TPREL_LO12_I
|
||||||
|
|| type == R_RISCV_TPREL_LO12_S)
|
||||||
relax_func = _bfd_riscv_relax_tls_le;
|
relax_func = _bfd_riscv_relax_tls_le;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Only relax this reloc if it is paired with R_RISCV_RELAX. */
|
||||||
|
if (i == sec->reloc_count - 1
|
||||||
|
|| ELFNN_R_TYPE ((rel + 1)->r_info) != R_RISCV_RELAX
|
||||||
|
|| rel->r_offset != (rel + 1)->r_offset)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Skip over the R_RISCV_RELAX. */
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
else if (type == R_RISCV_ALIGN)
|
else if (type == R_RISCV_ALIGN)
|
||||||
relax_func = _bfd_riscv_relax_align;
|
relax_func = _bfd_riscv_relax_align;
|
||||||
|
else
|
||||||
if (!relax_func)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
data->relocs = relocs;
|
data->relocs = relocs;
|
||||||
@ -2978,6 +3036,8 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
|
|||||||
/* A local symbol. */
|
/* A local symbol. */
|
||||||
Elf_Internal_Sym *isym = ((Elf_Internal_Sym *) symtab_hdr->contents
|
Elf_Internal_Sym *isym = ((Elf_Internal_Sym *) symtab_hdr->contents
|
||||||
+ ELFNN_R_SYM (rel->r_info));
|
+ ELFNN_R_SYM (rel->r_info));
|
||||||
|
reserve_size = (isym->st_size - rel->r_addend) > isym->st_size
|
||||||
|
? 0 : isym->st_size - rel->r_addend;
|
||||||
|
|
||||||
if (isym->st_shndx == SHN_UNDEF)
|
if (isym->st_shndx == SHN_UNDEF)
|
||||||
sym_sec = sec, symval = sec_addr (sec) + rel->r_offset;
|
sym_sec = sec, symval = sec_addr (sec) + rel->r_offset;
|
||||||
@ -3011,13 +3071,16 @@ _bfd_riscv_relax_section (bfd *abfd, asection *sec,
|
|||||||
else
|
else
|
||||||
symval = sec_addr (h->root.u.def.section) + h->root.u.def.value;
|
symval = sec_addr (h->root.u.def.section) + h->root.u.def.value;
|
||||||
|
|
||||||
|
if (h->type != STT_FUNC)
|
||||||
|
reserve_size =
|
||||||
|
(h->size - rel->r_addend) > h->size ? 0 : h->size - rel->r_addend;
|
||||||
sym_sec = h->root.u.def.section;
|
sym_sec = h->root.u.def.section;
|
||||||
}
|
}
|
||||||
|
|
||||||
symval += rel->r_addend;
|
symval += rel->r_addend;
|
||||||
|
|
||||||
if (!relax_func (abfd, sec, sym_sec, info, rel, symval,
|
if (!relax_func (abfd, sec, sym_sec, info, rel, symval,
|
||||||
max_alignment, again))
|
max_alignment, reserve_size, again))
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -713,6 +713,126 @@ static reloc_howto_type howto_table[] =
|
|||||||
0, /* src_mask */
|
0, /* src_mask */
|
||||||
ENCODE_STYPE_IMM (-1U), /* dst_mask */
|
ENCODE_STYPE_IMM (-1U), /* dst_mask */
|
||||||
FALSE), /* pcrel_offset */
|
FALSE), /* pcrel_offset */
|
||||||
|
|
||||||
|
/* TP-relative TLS LE load. */
|
||||||
|
HOWTO (R_RISCV_TPREL_I, /* type */
|
||||||
|
0, /* rightshift */
|
||||||
|
2, /* size */
|
||||||
|
32, /* bitsize */
|
||||||
|
FALSE, /* pc_relative */
|
||||||
|
0, /* bitpos */
|
||||||
|
complain_overflow_signed, /* complain_on_overflow */
|
||||||
|
bfd_elf_generic_reloc, /* special_function */
|
||||||
|
"R_RISCV_TPREL_I", /* name */
|
||||||
|
FALSE, /* partial_inplace */
|
||||||
|
0, /* src_mask */
|
||||||
|
ENCODE_ITYPE_IMM (-1U), /* dst_mask */
|
||||||
|
FALSE), /* pcrel_offset */
|
||||||
|
|
||||||
|
/* TP-relative TLS LE store. */
|
||||||
|
HOWTO (R_RISCV_TPREL_S, /* type */
|
||||||
|
0, /* rightshift */
|
||||||
|
2, /* size */
|
||||||
|
32, /* bitsize */
|
||||||
|
FALSE, /* pc_relative */
|
||||||
|
0, /* bitpos */
|
||||||
|
complain_overflow_signed, /* complain_on_overflow */
|
||||||
|
bfd_elf_generic_reloc, /* special_function */
|
||||||
|
"R_RISCV_TPREL_S", /* name */
|
||||||
|
FALSE, /* partial_inplace */
|
||||||
|
0, /* src_mask */
|
||||||
|
ENCODE_STYPE_IMM (-1U), /* dst_mask */
|
||||||
|
FALSE), /* pcrel_offset */
|
||||||
|
|
||||||
|
/* The paired relocation may be relaxed. */
|
||||||
|
HOWTO (R_RISCV_RELAX, /* type */
|
||||||
|
0, /* rightshift */
|
||||||
|
3, /* size */
|
||||||
|
0, /* bitsize */
|
||||||
|
FALSE, /* pc_relative */
|
||||||
|
0, /* bitpos */
|
||||||
|
complain_overflow_dont, /* complain_on_overflow */
|
||||||
|
bfd_elf_generic_reloc, /* special_function */
|
||||||
|
"R_RISCV_RELAX", /* name */
|
||||||
|
FALSE, /* partial_inplace */
|
||||||
|
0, /* src_mask */
|
||||||
|
0, /* dst_mask */
|
||||||
|
FALSE), /* pcrel_offset */
|
||||||
|
|
||||||
|
/* 6-bit in-place addition, for local label subtraction. */
|
||||||
|
HOWTO (R_RISCV_SUB6, /* type */
|
||||||
|
0, /* rightshift */
|
||||||
|
0, /* size */
|
||||||
|
8, /* bitsize */
|
||||||
|
FALSE, /* pc_relative */
|
||||||
|
0, /* bitpos */
|
||||||
|
complain_overflow_dont, /* complain_on_overflow */
|
||||||
|
bfd_elf_generic_reloc, /* special_function */
|
||||||
|
"R_RISCV_SUB6", /* name */
|
||||||
|
FALSE, /* partial_inplace */
|
||||||
|
0, /* src_mask */
|
||||||
|
0x3f, /* dst_mask */
|
||||||
|
FALSE), /* pcrel_offset */
|
||||||
|
|
||||||
|
/* 6-bit in-place setting, for local label subtraction. */
|
||||||
|
HOWTO (R_RISCV_SET6, /* type */
|
||||||
|
0, /* rightshift */
|
||||||
|
0, /* size */
|
||||||
|
8, /* bitsize */
|
||||||
|
FALSE, /* pc_relative */
|
||||||
|
0, /* bitpos */
|
||||||
|
complain_overflow_dont, /* complain_on_overflow */
|
||||||
|
bfd_elf_generic_reloc, /* special_function */
|
||||||
|
"R_RISCV_SET6", /* name */
|
||||||
|
FALSE, /* partial_inplace */
|
||||||
|
0, /* src_mask */
|
||||||
|
0x3f, /* dst_mask */
|
||||||
|
FALSE), /* pcrel_offset */
|
||||||
|
|
||||||
|
/* 8-bit in-place setting, for local label subtraction. */
|
||||||
|
HOWTO (R_RISCV_SET8, /* type */
|
||||||
|
0, /* rightshift */
|
||||||
|
0, /* size */
|
||||||
|
8, /* bitsize */
|
||||||
|
FALSE, /* pc_relative */
|
||||||
|
0, /* bitpos */
|
||||||
|
complain_overflow_dont, /* complain_on_overflow */
|
||||||
|
bfd_elf_generic_reloc, /* special_function */
|
||||||
|
"R_RISCV_SET8", /* name */
|
||||||
|
FALSE, /* partial_inplace */
|
||||||
|
0, /* src_mask */
|
||||||
|
MINUS_ONE, /* dst_mask */
|
||||||
|
FALSE), /* pcrel_offset */
|
||||||
|
|
||||||
|
/* 16-bit in-place setting, for local label subtraction. */
|
||||||
|
HOWTO (R_RISCV_SET16, /* type */
|
||||||
|
0, /* rightshift */
|
||||||
|
1, /* size */
|
||||||
|
16, /* bitsize */
|
||||||
|
FALSE, /* pc_relative */
|
||||||
|
0, /* bitpos */
|
||||||
|
complain_overflow_dont, /* complain_on_overflow */
|
||||||
|
bfd_elf_generic_reloc, /* special_function */
|
||||||
|
"R_RISCV_SET16", /* name */
|
||||||
|
FALSE, /* partial_inplace */
|
||||||
|
0, /* src_mask */
|
||||||
|
MINUS_ONE, /* dst_mask */
|
||||||
|
FALSE), /* pcrel_offset */
|
||||||
|
|
||||||
|
/* 32-bit in-place setting, for local label subtraction. */
|
||||||
|
HOWTO (R_RISCV_SET32, /* type */
|
||||||
|
0, /* rightshift */
|
||||||
|
2, /* size */
|
||||||
|
32, /* bitsize */
|
||||||
|
FALSE, /* pc_relative */
|
||||||
|
0, /* bitpos */
|
||||||
|
complain_overflow_dont, /* complain_on_overflow */
|
||||||
|
bfd_elf_generic_reloc, /* special_function */
|
||||||
|
"R_RISCV_SET32", /* name */
|
||||||
|
FALSE, /* partial_inplace */
|
||||||
|
0, /* src_mask */
|
||||||
|
MINUS_ONE, /* dst_mask */
|
||||||
|
FALSE), /* pcrel_offset */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A mapping from BFD reloc types to RISC-V ELF reloc types. */
|
/* A mapping from BFD reloc types to RISC-V ELF reloc types. */
|
||||||
@ -766,6 +886,14 @@ static const struct elf_reloc_map riscv_reloc_map[] =
|
|||||||
{ BFD_RELOC_RISCV_RVC_LUI, R_RISCV_RVC_LUI },
|
{ BFD_RELOC_RISCV_RVC_LUI, R_RISCV_RVC_LUI },
|
||||||
{ BFD_RELOC_RISCV_GPREL_I, R_RISCV_GPREL_I },
|
{ BFD_RELOC_RISCV_GPREL_I, R_RISCV_GPREL_I },
|
||||||
{ BFD_RELOC_RISCV_GPREL_S, R_RISCV_GPREL_S },
|
{ BFD_RELOC_RISCV_GPREL_S, R_RISCV_GPREL_S },
|
||||||
|
{ BFD_RELOC_RISCV_TPREL_I, R_RISCV_TPREL_I },
|
||||||
|
{ BFD_RELOC_RISCV_TPREL_S, R_RISCV_TPREL_S },
|
||||||
|
{ BFD_RELOC_RISCV_RELAX, R_RISCV_RELAX },
|
||||||
|
{ BFD_RELOC_RISCV_SUB6, R_RISCV_SUB6 },
|
||||||
|
{ BFD_RELOC_RISCV_SET6, R_RISCV_SET6 },
|
||||||
|
{ BFD_RELOC_RISCV_SET8, R_RISCV_SET8 },
|
||||||
|
{ BFD_RELOC_RISCV_SET16, R_RISCV_SET16 },
|
||||||
|
{ BFD_RELOC_RISCV_SET32, R_RISCV_SET32 },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Given a BFD reloc type, return a howto structure. */
|
/* Given a BFD reloc type, return a howto structure. */
|
||||||
|
@ -2204,6 +2204,15 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
|
|||||||
"BFD_RELOC_RISCV_RVC_LUI",
|
"BFD_RELOC_RISCV_RVC_LUI",
|
||||||
"BFD_RELOC_RISCV_GPREL_I",
|
"BFD_RELOC_RISCV_GPREL_I",
|
||||||
"BFD_RELOC_RISCV_GPREL_S",
|
"BFD_RELOC_RISCV_GPREL_S",
|
||||||
|
"BFD_RELOC_RISCV_TPREL_I",
|
||||||
|
"BFD_RELOC_RISCV_TPREL_S",
|
||||||
|
"BFD_RELOC_RISCV_RELAX",
|
||||||
|
"BFD_RELOC_RISCV_CFA",
|
||||||
|
"BFD_RELOC_RISCV_SUB6",
|
||||||
|
"BFD_RELOC_RISCV_SET6",
|
||||||
|
"BFD_RELOC_RISCV_SET8",
|
||||||
|
"BFD_RELOC_RISCV_SET16",
|
||||||
|
"BFD_RELOC_RISCV_SET32",
|
||||||
"BFD_RELOC_RL78_NEG8",
|
"BFD_RELOC_RL78_NEG8",
|
||||||
"BFD_RELOC_RL78_NEG16",
|
"BFD_RELOC_RL78_NEG16",
|
||||||
"BFD_RELOC_RL78_NEG24",
|
"BFD_RELOC_RL78_NEG24",
|
||||||
|
18
bfd/reloc.c
18
bfd/reloc.c
@ -5124,6 +5124,24 @@ ENUMX
|
|||||||
BFD_RELOC_RISCV_GPREL_I
|
BFD_RELOC_RISCV_GPREL_I
|
||||||
ENUMX
|
ENUMX
|
||||||
BFD_RELOC_RISCV_GPREL_S
|
BFD_RELOC_RISCV_GPREL_S
|
||||||
|
ENUMX
|
||||||
|
BFD_RELOC_RISCV_TPREL_I
|
||||||
|
ENUMX
|
||||||
|
BFD_RELOC_RISCV_TPREL_S
|
||||||
|
ENUMX
|
||||||
|
BFD_RELOC_RISCV_RELAX
|
||||||
|
ENUMX
|
||||||
|
BFD_RELOC_RISCV_CFA
|
||||||
|
ENUMX
|
||||||
|
BFD_RELOC_RISCV_SUB6
|
||||||
|
ENUMX
|
||||||
|
BFD_RELOC_RISCV_SET6
|
||||||
|
ENUMX
|
||||||
|
BFD_RELOC_RISCV_SET8
|
||||||
|
ENUMX
|
||||||
|
BFD_RELOC_RISCV_SET16
|
||||||
|
ENUMX
|
||||||
|
BFD_RELOC_RISCV_SET32
|
||||||
ENUMDOC
|
ENUMDOC
|
||||||
RISC-V relocations.
|
RISC-V relocations.
|
||||||
|
|
||||||
|
@ -1,3 +1,22 @@
|
|||||||
|
2016-12-20 Andrew Waterman <andrew@sifive.com>
|
||||||
|
Kuan-Lin Chen <kuanlinchentw@gmail.com>
|
||||||
|
|
||||||
|
* config/tc-riscv.c (riscv_set_options): Add relax.
|
||||||
|
(riscv_opts): Likewise.
|
||||||
|
(s_riscv_option): Add relax and norelax.
|
||||||
|
(riscv_apply_const_reloc): New function.
|
||||||
|
(append_insn): Move constant relocation handling to
|
||||||
|
riscv_apply_const_reloc.
|
||||||
|
(md_pcrel_from): Likewise.
|
||||||
|
(parse_relocation): Skip BFD_RELOC_UNUSED.
|
||||||
|
(md_pcrel_from): Handle BFD_RELOC_RISCV_SUB6,
|
||||||
|
BFD_RELOC_RISCV_RELAX, BFD_RELOC_RISCV_CFA.
|
||||||
|
(md_apply_fix): Likewise.
|
||||||
|
(riscv_pre_output_hook): New function.
|
||||||
|
* config/tc-riscv.h (md_pre_output_hook): Define.
|
||||||
|
(riscv_pre_output_hook): Declare.
|
||||||
|
(DWARF_CIE_DATA_ALIGNMENT): Always -4.
|
||||||
|
|
||||||
2016-12-20 Andrew Waterman <andrew@sifive.com>
|
2016-12-20 Andrew Waterman <andrew@sifive.com>
|
||||||
|
|
||||||
* config/tc-riscv.c: Formatting and comment fixes throughout.
|
* config/tc-riscv.c: Formatting and comment fixes throughout.
|
||||||
|
@ -74,12 +74,14 @@ struct riscv_set_options
|
|||||||
{
|
{
|
||||||
int pic; /* Generate position-independent code. */
|
int pic; /* Generate position-independent code. */
|
||||||
int rvc; /* Generate RVC code. */
|
int rvc; /* Generate RVC code. */
|
||||||
|
int relax; /* Emit relocs the linker is allowed to relax. */
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct riscv_set_options riscv_opts =
|
static struct riscv_set_options riscv_opts =
|
||||||
{
|
{
|
||||||
0, /* pic */
|
0, /* pic */
|
||||||
0, /* rvc */
|
0, /* rvc */
|
||||||
|
1, /* relax */
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -648,6 +650,28 @@ md_begin (void)
|
|||||||
record_alignment (text_section, riscv_opts.rvc ? 1 : 2);
|
record_alignment (text_section, riscv_opts.rvc ? 1 : 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static insn_t
|
||||||
|
riscv_apply_const_reloc (bfd_reloc_code_real_type reloc_type, bfd_vma value)
|
||||||
|
{
|
||||||
|
switch (reloc_type)
|
||||||
|
{
|
||||||
|
case BFD_RELOC_32:
|
||||||
|
return value;
|
||||||
|
|
||||||
|
case BFD_RELOC_RISCV_HI20:
|
||||||
|
return ENCODE_UTYPE_IMM (RISCV_CONST_HIGH_PART (value));
|
||||||
|
|
||||||
|
case BFD_RELOC_RISCV_LO12_S:
|
||||||
|
return ENCODE_STYPE_IMM (value);
|
||||||
|
|
||||||
|
case BFD_RELOC_RISCV_LO12_I:
|
||||||
|
return ENCODE_ITYPE_IMM (value);
|
||||||
|
|
||||||
|
default:
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Output an instruction. IP is the instruction information.
|
/* Output an instruction. IP is the instruction information.
|
||||||
ADDRESS_EXPR is an operand of the instruction to be used with
|
ADDRESS_EXPR is an operand of the instruction to be used with
|
||||||
RELOC_TYPE. */
|
RELOC_TYPE. */
|
||||||
@ -676,43 +700,22 @@ append_insn (struct riscv_cl_insn *ip, expressionS *address_expr,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (address_expr->X_op == O_constant)
|
else if (address_expr->X_op == O_constant)
|
||||||
|
ip->insn_opcode |= riscv_apply_const_reloc (reloc_type,
|
||||||
|
address_expr->X_add_number);
|
||||||
|
else
|
||||||
{
|
{
|
||||||
switch (reloc_type)
|
howto = bfd_reloc_type_lookup (stdoutput, reloc_type);
|
||||||
{
|
if (howto == NULL)
|
||||||
case BFD_RELOC_32:
|
as_bad (_("Unsupported RISC-V relocation number %d"), reloc_type);
|
||||||
ip->insn_opcode |= address_expr->X_add_number;
|
|
||||||
goto append;
|
|
||||||
|
|
||||||
case BFD_RELOC_RISCV_HI20:
|
ip->fixp = fix_new_exp (ip->frag, ip->where,
|
||||||
{
|
bfd_get_reloc_size (howto),
|
||||||
insn_t imm = RISCV_CONST_HIGH_PART (address_expr->X_add_number);
|
address_expr, FALSE, reloc_type);
|
||||||
ip->insn_opcode |= ENCODE_UTYPE_IMM (imm);
|
|
||||||
goto append;
|
|
||||||
}
|
|
||||||
|
|
||||||
case BFD_RELOC_RISCV_LO12_S:
|
ip->fixp->fx_tcbit = riscv_opts.relax;
|
||||||
ip->insn_opcode |= ENCODE_STYPE_IMM (address_expr->X_add_number);
|
|
||||||
goto append;
|
|
||||||
|
|
||||||
case BFD_RELOC_RISCV_LO12_I:
|
|
||||||
ip->insn_opcode |= ENCODE_ITYPE_IMM (address_expr->X_add_number);
|
|
||||||
goto append;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
howto = bfd_reloc_type_lookup (stdoutput, reloc_type);
|
|
||||||
if (howto == NULL)
|
|
||||||
as_bad (_("Unsupported RISC-V relocation number %d"), reloc_type);
|
|
||||||
|
|
||||||
ip->fixp = fix_new_exp (ip->frag, ip->where,
|
|
||||||
bfd_get_reloc_size (howto),
|
|
||||||
address_expr, FALSE, reloc_type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
append:
|
|
||||||
add_fixed_insn (ip);
|
add_fixed_insn (ip);
|
||||||
install_insn (ip);
|
install_insn (ip);
|
||||||
}
|
}
|
||||||
@ -1085,7 +1088,8 @@ parse_relocation (char **str, bfd_reloc_code_real_type *reloc,
|
|||||||
|
|
||||||
/* Check whether the output BFD supports this relocation.
|
/* Check whether the output BFD supports this relocation.
|
||||||
If not, issue an error and fall back on something safe. */
|
If not, issue an error and fall back on something safe. */
|
||||||
if (!bfd_reloc_type_lookup (stdoutput, percent_op->reloc))
|
if (*reloc != BFD_RELOC_UNUSED
|
||||||
|
&& !bfd_reloc_type_lookup (stdoutput, *reloc))
|
||||||
{
|
{
|
||||||
as_bad ("relocation %s isn't supported by the current ABI",
|
as_bad ("relocation %s isn't supported by the current ABI",
|
||||||
percent_op->str);
|
percent_op->str);
|
||||||
@ -1826,45 +1830,56 @@ md_pcrel_from (fixS *fixP)
|
|||||||
void
|
void
|
||||||
md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
|
md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
|
unsigned int subtype;
|
||||||
bfd_byte *buf = (bfd_byte *) (fixP->fx_frag->fr_literal + fixP->fx_where);
|
bfd_byte *buf = (bfd_byte *) (fixP->fx_frag->fr_literal + fixP->fx_where);
|
||||||
|
bfd_boolean relaxable = FALSE;
|
||||||
|
|
||||||
/* Remember value for tc_gen_reloc. */
|
/* Remember value for tc_gen_reloc. */
|
||||||
fixP->fx_addnumber = *valP;
|
fixP->fx_addnumber = *valP;
|
||||||
|
|
||||||
switch (fixP->fx_r_type)
|
switch (fixP->fx_r_type)
|
||||||
{
|
{
|
||||||
case BFD_RELOC_RISCV_TLS_GOT_HI20:
|
|
||||||
case BFD_RELOC_RISCV_TLS_GD_HI20:
|
|
||||||
case BFD_RELOC_RISCV_TLS_DTPREL32:
|
|
||||||
case BFD_RELOC_RISCV_TLS_DTPREL64:
|
|
||||||
case BFD_RELOC_RISCV_TPREL_HI20:
|
|
||||||
case BFD_RELOC_RISCV_TPREL_LO12_I:
|
|
||||||
case BFD_RELOC_RISCV_TPREL_LO12_S:
|
|
||||||
case BFD_RELOC_RISCV_TPREL_ADD:
|
|
||||||
S_SET_THREAD_LOCAL (fixP->fx_addsy);
|
|
||||||
/* Fall through. */
|
|
||||||
|
|
||||||
case BFD_RELOC_RISCV_GOT_HI20:
|
|
||||||
case BFD_RELOC_RISCV_PCREL_HI20:
|
|
||||||
case BFD_RELOC_RISCV_HI20:
|
case BFD_RELOC_RISCV_HI20:
|
||||||
case BFD_RELOC_RISCV_LO12_I:
|
case BFD_RELOC_RISCV_LO12_I:
|
||||||
case BFD_RELOC_RISCV_LO12_S:
|
case BFD_RELOC_RISCV_LO12_S:
|
||||||
|
bfd_putl32 (riscv_apply_const_reloc (fixP->fx_r_type, *valP)
|
||||||
|
| bfd_getl32 (buf), buf);
|
||||||
|
relaxable = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BFD_RELOC_RISCV_GOT_HI20:
|
||||||
|
case BFD_RELOC_RISCV_PCREL_HI20:
|
||||||
case BFD_RELOC_RISCV_ADD8:
|
case BFD_RELOC_RISCV_ADD8:
|
||||||
case BFD_RELOC_RISCV_ADD16:
|
case BFD_RELOC_RISCV_ADD16:
|
||||||
case BFD_RELOC_RISCV_ADD32:
|
case BFD_RELOC_RISCV_ADD32:
|
||||||
case BFD_RELOC_RISCV_ADD64:
|
case BFD_RELOC_RISCV_ADD64:
|
||||||
|
case BFD_RELOC_RISCV_SUB6:
|
||||||
case BFD_RELOC_RISCV_SUB8:
|
case BFD_RELOC_RISCV_SUB8:
|
||||||
case BFD_RELOC_RISCV_SUB16:
|
case BFD_RELOC_RISCV_SUB16:
|
||||||
case BFD_RELOC_RISCV_SUB32:
|
case BFD_RELOC_RISCV_SUB32:
|
||||||
case BFD_RELOC_RISCV_SUB64:
|
case BFD_RELOC_RISCV_SUB64:
|
||||||
gas_assert (fixP->fx_addsy != NULL);
|
case BFD_RELOC_RISCV_RELAX:
|
||||||
/* Nothing needed to do. The value comes from the reloc entry. */
|
break;
|
||||||
|
|
||||||
|
case BFD_RELOC_RISCV_TPREL_HI20:
|
||||||
|
case BFD_RELOC_RISCV_TPREL_LO12_I:
|
||||||
|
case BFD_RELOC_RISCV_TPREL_LO12_S:
|
||||||
|
case BFD_RELOC_RISCV_TPREL_ADD:
|
||||||
|
relaxable = TRUE;
|
||||||
|
/* Fall through. */
|
||||||
|
|
||||||
|
case BFD_RELOC_RISCV_TLS_GOT_HI20:
|
||||||
|
case BFD_RELOC_RISCV_TLS_GD_HI20:
|
||||||
|
case BFD_RELOC_RISCV_TLS_DTPREL32:
|
||||||
|
case BFD_RELOC_RISCV_TLS_DTPREL64:
|
||||||
|
S_SET_THREAD_LOCAL (fixP->fx_addsy);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BFD_RELOC_64:
|
case BFD_RELOC_64:
|
||||||
case BFD_RELOC_32:
|
case BFD_RELOC_32:
|
||||||
case BFD_RELOC_16:
|
case BFD_RELOC_16:
|
||||||
case BFD_RELOC_8:
|
case BFD_RELOC_8:
|
||||||
|
case BFD_RELOC_RISCV_CFA:
|
||||||
if (fixP->fx_addsy && fixP->fx_subsy)
|
if (fixP->fx_addsy && fixP->fx_subsy)
|
||||||
{
|
{
|
||||||
fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
|
fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
|
||||||
@ -1895,6 +1910,49 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
|
|||||||
fixP->fx_next->fx_r_type = BFD_RELOC_RISCV_SUB8;
|
fixP->fx_next->fx_r_type = BFD_RELOC_RISCV_SUB8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case BFD_RELOC_RISCV_CFA:
|
||||||
|
/* Load the byte to get the subtype. */
|
||||||
|
subtype = bfd_get_8 (NULL, &fixP->fx_frag->fr_literal[fixP->fx_where]);
|
||||||
|
switch (subtype)
|
||||||
|
{
|
||||||
|
case DW_CFA_advance_loc1:
|
||||||
|
fixP->fx_where++;
|
||||||
|
fixP->fx_next->fx_where++;
|
||||||
|
fixP->fx_r_type = BFD_RELOC_RISCV_SET8;
|
||||||
|
fixP->fx_next->fx_r_type = BFD_RELOC_RISCV_SUB8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DW_CFA_advance_loc2:
|
||||||
|
fixP->fx_size = 2;
|
||||||
|
fixP->fx_where++;
|
||||||
|
fixP->fx_next->fx_size = 2;
|
||||||
|
fixP->fx_next->fx_where++;
|
||||||
|
fixP->fx_r_type = BFD_RELOC_RISCV_SET16;
|
||||||
|
fixP->fx_next->fx_r_type = BFD_RELOC_RISCV_SUB16;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DW_CFA_advance_loc4:
|
||||||
|
fixP->fx_size = 4;
|
||||||
|
fixP->fx_where++;
|
||||||
|
fixP->fx_next->fx_size = 4;
|
||||||
|
fixP->fx_next->fx_where++;
|
||||||
|
fixP->fx_r_type = BFD_RELOC_RISCV_SET32;
|
||||||
|
fixP->fx_next->fx_r_type = BFD_RELOC_RISCV_SUB32;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (subtype < 0x80 && (subtype & 0x40))
|
||||||
|
{
|
||||||
|
/* DW_CFA_advance_loc */
|
||||||
|
fixP->fx_r_type = BFD_RELOC_RISCV_SET6;
|
||||||
|
fixP->fx_next->fx_r_type = BFD_RELOC_RISCV_SUB6;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
as_fatal (_("internal error: bad CFA value #%d"), subtype);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* This case is unreachable. */
|
/* This case is unreachable. */
|
||||||
abort ();
|
abort ();
|
||||||
@ -1954,10 +2012,13 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BFD_RELOC_RISCV_PCREL_LO12_S:
|
|
||||||
case BFD_RELOC_RISCV_PCREL_LO12_I:
|
|
||||||
case BFD_RELOC_RISCV_CALL:
|
case BFD_RELOC_RISCV_CALL:
|
||||||
case BFD_RELOC_RISCV_CALL_PLT:
|
case BFD_RELOC_RISCV_CALL_PLT:
|
||||||
|
relaxable = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BFD_RELOC_RISCV_PCREL_LO12_S:
|
||||||
|
case BFD_RELOC_RISCV_PCREL_LO12_I:
|
||||||
case BFD_RELOC_RISCV_ALIGN:
|
case BFD_RELOC_RISCV_ALIGN:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1966,8 +2027,54 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
|
|||||||
if (bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type) != NULL)
|
if (bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type) != NULL)
|
||||||
as_fatal (_("internal error: bad relocation #%d"), fixP->fx_r_type);
|
as_fatal (_("internal error: bad relocation #%d"), fixP->fx_r_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add an R_RISCV_RELAX reloc if the reloc is relaxable. */
|
||||||
|
if (relaxable && fixP->fx_tcbit && fixP->fx_addsy != NULL)
|
||||||
|
{
|
||||||
|
fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
|
||||||
|
fixP->fx_next->fx_addsy = fixP->fx_next->fx_subsy = NULL;
|
||||||
|
fixP->fx_next->fx_r_type = BFD_RELOC_RISCV_RELAX;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Because the value of .cfi_remember_state may changed after relaxation,
|
||||||
|
we insert a fix to relocate it again in link-time. */
|
||||||
|
|
||||||
|
void
|
||||||
|
riscv_pre_output_hook (void)
|
||||||
|
{
|
||||||
|
const frchainS *frch;
|
||||||
|
const asection *s;
|
||||||
|
|
||||||
|
for (s = stdoutput->sections; s; s = s->next)
|
||||||
|
for (frch = seg_info (s)->frchainP; frch; frch = frch->frch_next)
|
||||||
|
{
|
||||||
|
const fragS *frag;
|
||||||
|
|
||||||
|
for (frag = frch->frch_root; frag; frag = frag->fr_next)
|
||||||
|
{
|
||||||
|
if (frag->fr_type == rs_cfa)
|
||||||
|
{
|
||||||
|
const fragS *loc4_frag;
|
||||||
|
expressionS exp;
|
||||||
|
|
||||||
|
symbolS *add_symbol = frag->fr_symbol->sy_value.X_add_symbol;
|
||||||
|
symbolS *op_symbol = frag->fr_symbol->sy_value.X_op_symbol;
|
||||||
|
|
||||||
|
exp.X_op = O_subtract;
|
||||||
|
exp.X_add_symbol = add_symbol;
|
||||||
|
exp.X_add_number = 0;
|
||||||
|
exp.X_op_symbol = op_symbol;
|
||||||
|
|
||||||
|
loc4_frag = (fragS *) frag->fr_opcode;
|
||||||
|
fix_new_exp (loc4_frag, (int) frag->fr_offset, 1, &exp, 0,
|
||||||
|
BFD_RELOC_RISCV_CFA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* This structure is used to hold a stack of .option values. */
|
/* This structure is used to hold a stack of .option values. */
|
||||||
|
|
||||||
struct riscv_option_stack
|
struct riscv_option_stack
|
||||||
@ -1998,10 +2105,10 @@ s_riscv_option (int x ATTRIBUTE_UNUSED)
|
|||||||
riscv_opts.pic = TRUE;
|
riscv_opts.pic = TRUE;
|
||||||
else if (strcmp (name, "nopic") == 0)
|
else if (strcmp (name, "nopic") == 0)
|
||||||
riscv_opts.pic = FALSE;
|
riscv_opts.pic = FALSE;
|
||||||
else if (strcmp (name, "soft-float") == 0)
|
else if (strcmp (name, "relax") == 0)
|
||||||
float_mode = FLOAT_MODE_SOFT;
|
riscv_opts.relax = TRUE;
|
||||||
else if (strcmp (name, "hard-float") == 0)
|
else if (strcmp (name, "norelax") == 0)
|
||||||
float_mode = FLOAT_MODE_HARD;
|
riscv_opts.relax = FALSE;
|
||||||
else if (strcmp (name, "push") == 0)
|
else if (strcmp (name, "push") == 0)
|
||||||
{
|
{
|
||||||
struct riscv_option_stack *s;
|
struct riscv_option_stack *s;
|
||||||
|
@ -61,6 +61,9 @@ extern void riscv_after_parse_args (void);
|
|||||||
#define md_parse_long_option(arg) riscv_parse_long_option (arg)
|
#define md_parse_long_option(arg) riscv_parse_long_option (arg)
|
||||||
extern int riscv_parse_long_option (const char *);
|
extern int riscv_parse_long_option (const char *);
|
||||||
|
|
||||||
|
#define md_pre_output_hook riscv_pre_output_hook()
|
||||||
|
extern void riscv_pre_output_hook (void);
|
||||||
|
|
||||||
/* Let the linker resolve all the relocs due to relaxation. */
|
/* Let the linker resolve all the relocs due to relaxation. */
|
||||||
#define tc_fix_adjustable(fixp) 0
|
#define tc_fix_adjustable(fixp) 0
|
||||||
#define md_allow_local_subtract(l,r,s) 0
|
#define md_allow_local_subtract(l,r,s) 0
|
||||||
@ -93,7 +96,9 @@ extern int tc_riscv_regname_to_dw2regnum (char *);
|
|||||||
|
|
||||||
extern unsigned xlen;
|
extern unsigned xlen;
|
||||||
#define DWARF2_DEFAULT_RETURN_COLUMN X_RA
|
#define DWARF2_DEFAULT_RETURN_COLUMN X_RA
|
||||||
#define DWARF2_CIE_DATA_ALIGNMENT (-(int) (xlen / 8))
|
|
||||||
|
/* Even on RV64, use 4-byte alignment, as F registers may be only 32 bits. */
|
||||||
|
#define DWARF2_CIE_DATA_ALIGNMENT -4
|
||||||
|
|
||||||
#define elf_tc_final_processing riscv_elf_final_processing
|
#define elf_tc_final_processing riscv_elf_final_processing
|
||||||
extern void riscv_elf_final_processing (void);
|
extern void riscv_elf_final_processing (void);
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
2016-12-20 Andrew Waterman <andrew@sifive.com>
|
||||||
|
Kuan-Lin Chen <kuanlinchentw@gmail.com>
|
||||||
|
|
||||||
|
* elf/riscv.h: Add R_RISCV_TPREL_I through R_RISCV_SET32.
|
||||||
|
|
||||||
2016-12-16 fincs <fincs.alt1@gmail.com>
|
2016-12-16 fincs <fincs.alt1@gmail.com>
|
||||||
|
|
||||||
* bfdlink.h (struct bfd_link_info): Add gc_keep_exported.
|
* bfdlink.h (struct bfd_link_info): Add gc_keep_exported.
|
||||||
|
@ -79,6 +79,14 @@ START_RELOC_NUMBERS (elf_riscv_reloc_type)
|
|||||||
RELOC_NUMBER (R_RISCV_RVC_LUI, 46)
|
RELOC_NUMBER (R_RISCV_RVC_LUI, 46)
|
||||||
RELOC_NUMBER (R_RISCV_GPREL_I, 47)
|
RELOC_NUMBER (R_RISCV_GPREL_I, 47)
|
||||||
RELOC_NUMBER (R_RISCV_GPREL_S, 48)
|
RELOC_NUMBER (R_RISCV_GPREL_S, 48)
|
||||||
|
RELOC_NUMBER (R_RISCV_TPREL_I, 49)
|
||||||
|
RELOC_NUMBER (R_RISCV_TPREL_S, 50)
|
||||||
|
RELOC_NUMBER (R_RISCV_RELAX, 51)
|
||||||
|
RELOC_NUMBER (R_RISCV_SUB6, 52)
|
||||||
|
RELOC_NUMBER (R_RISCV_SET6, 53)
|
||||||
|
RELOC_NUMBER (R_RISCV_SET8, 54)
|
||||||
|
RELOC_NUMBER (R_RISCV_SET16, 55)
|
||||||
|
RELOC_NUMBER (R_RISCV_SET32, 56)
|
||||||
END_RELOC_NUMBERS (R_RISCV_max)
|
END_RELOC_NUMBERS (R_RISCV_max)
|
||||||
|
|
||||||
/* Processor specific flags for the ELF header e_flags field. */
|
/* Processor specific flags for the ELF header e_flags field. */
|
||||||
|
Reference in New Issue
Block a user