From: Kuan-Lin Chen Date: Mon, 31 Jul 2017 14:33:48 +0000 (+0100) Subject: Improve handling of ADD and SUB relocations on the RISCV target. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=575934368531e7592a7576a39a4320d88007ce88;p=binutils-gdb.git Improve handling of ADD and SUB relocations on the RISCV target. * elfxx-riscv.c (riscv_elf_add_sub_reloc): New function. * (howto_table) [R_RISCV_ADD8]: Use riscv_elf_add_sub_reloc. [R_RISCV_ADD16]: Likewise. [R_RISCV_ADD32]: Likewise. [R_RISCV_ADD64]: Likewise. [R_RISCV_SUB6]: Likewise. [R_RISCV_SUB8]: Likewise. [R_RISCV_SUB16]: Likewise. [R_RISCV_SUB32]: Likewise. [R_RISCV_SUB64]: Likewise. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 9839a3487f5..1c0c65b58cf 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,16 @@ +2017-07-31 Kuan-Lin Chen + + * elfxx-riscv.c (riscv_elf_add_sub_reloc): New function. + * (howto_table) [R_RISCV_ADD8]: Use riscv_elf_add_sub_reloc. + [R_RISCV_ADD16]: Likewise. + [R_RISCV_ADD32]: Likewise. + [R_RISCV_ADD64]: Likewise. + [R_RISCV_SUB6]: Likewise. + [R_RISCV_SUB8]: Likewise. + [R_RISCV_SUB16]: Likewise. + [R_RISCV_SUB32]: Likewise. + [R_RISCV_SUB64]: Likewise. + 2017-07-31 Alan Modra * elf64-ppc.c (ppc64_elf_tls_setup): Warn on --plt-localentry diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c index 5fa98f37e98..55db39218e4 100644 --- a/bfd/elfxx-riscv.c +++ b/bfd/elfxx-riscv.c @@ -32,6 +32,13 @@ #define MINUS_ONE ((bfd_vma)0 - 1) +/* Special handler for ADD/SUB relocations that allows them to be filled out + both in the pre-linked and post-linked file. This is necessary to make + pre-linked debug info work, as due to linker relaxations we need to emit + relocations for the debug info. */ +static bfd_reloc_status_type riscv_elf_add_sub_reloc + (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); + /* The relocation table used for SHT_RELA sections. */ static reloc_howto_type howto_table[] = @@ -480,7 +487,7 @@ static reloc_howto_type howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + riscv_elf_add_sub_reloc, /* special_function */ "R_RISCV_ADD8", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -495,7 +502,7 @@ static reloc_howto_type howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + riscv_elf_add_sub_reloc, /* special_function */ "R_RISCV_ADD16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -510,7 +517,7 @@ static reloc_howto_type howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + riscv_elf_add_sub_reloc, /* special_function */ "R_RISCV_ADD32", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -525,7 +532,7 @@ static reloc_howto_type howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + riscv_elf_add_sub_reloc, /* special_function */ "R_RISCV_ADD64", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -540,7 +547,7 @@ static reloc_howto_type howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + riscv_elf_add_sub_reloc, /* special_function */ "R_RISCV_SUB8", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -555,7 +562,7 @@ static reloc_howto_type howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + riscv_elf_add_sub_reloc, /* special_function */ "R_RISCV_SUB16", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -570,7 +577,7 @@ static reloc_howto_type howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + riscv_elf_add_sub_reloc, /* special_function */ "R_RISCV_SUB32", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -585,7 +592,7 @@ static reloc_howto_type howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + riscv_elf_add_sub_reloc, /* special_function */ "R_RISCV_SUB64", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -767,7 +774,7 @@ static reloc_howto_type howto_table[] = FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ + riscv_elf_add_sub_reloc, /* special_function */ "R_RISCV_SUB6", /* name */ FALSE, /* partial_inplace */ 0, /* src_mask */ @@ -951,3 +958,54 @@ riscv_elf_rtype_to_howto (unsigned int r_type) } return &howto_table[r_type]; } + +/* Special_function of RISCV_ADD and RISCV_SUB relocations. */ + +static bfd_reloc_status_type +riscv_elf_add_sub_reloc (bfd *abfd, + arelent *reloc_entry, + asymbol *symbol, + void *data, + asection *input_section, + bfd *output_bfd, + char **error_message ATTRIBUTE_UNUSED) +{ + reloc_howto_type *howto = reloc_entry->howto; + bfd_vma relocation; + + if (output_bfd != NULL + && (symbol->flags & BSF_SECTION_SYM) == 0 + && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0)) + { + reloc_entry->address += input_section->output_offset; + return bfd_reloc_ok; + } + + if (output_bfd != NULL) + return bfd_reloc_continue; + + relocation = symbol->value + symbol->section->output_section->vma + + symbol->section->output_offset + reloc_entry->addend; + bfd_vma old_value = bfd_get (howto->bitsize, abfd, + data + reloc_entry->address); + + switch (howto->type) + { + case R_RISCV_ADD8: + case R_RISCV_ADD16: + case R_RISCV_ADD32: + case R_RISCV_ADD64: + relocation = old_value + relocation; + break; + case R_RISCV_SUB6: + case R_RISCV_SUB8: + case R_RISCV_SUB16: + case R_RISCV_SUB32: + case R_RISCV_SUB64: + relocation = old_value - relocation; + break; + } + bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address); + + return bfd_reloc_ok; +}