diff options
author | Kuan-Lin Chen <rufus@andestech.com> | 2017-07-31 15:33:48 +0100 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2017-07-31 15:33:48 +0100 |
commit | 575934368531e7592a7576a39a4320d88007ce88 (patch) | |
tree | 8d2f2b91796d01f712ad950ed21d0a6132dd419c /bfd/elfxx-riscv.c | |
parent | c48a4d983400ade9cfba0531905245eb454afe08 (diff) | |
download | gdb-575934368531e7592a7576a39a4320d88007ce88.zip gdb-575934368531e7592a7576a39a4320d88007ce88.tar.gz gdb-575934368531e7592a7576a39a4320d88007ce88.tar.bz2 |
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.
Diffstat (limited to 'bfd/elfxx-riscv.c')
-rw-r--r-- | bfd/elfxx-riscv.c | 76 |
1 files changed, 67 insertions, 9 deletions
diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c index 5fa98f3..55db392 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; +} |