diff options
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/bpf-reloc.def | 6 | ||||
-rw-r--r-- | bfd/elf64-bpf.c | 34 |
2 files changed, 26 insertions, 14 deletions
diff --git a/bfd/bpf-reloc.def b/bfd/bpf-reloc.def index 42ba1a1..65228d4 100644 --- a/bfd/bpf-reloc.def +++ b/bfd/bpf-reloc.def @@ -38,7 +38,7 @@ complain_overflow_bitfield, /* complain_on_overflow */ bpf_elf_generic_reloc, /* special_function */ "R_BPF_64_ABS32", /* name */ - false, /* partial_inplace */ + true, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ true) /* pcrel_offset */ @@ -53,7 +53,7 @@ complain_overflow_bitfield, /* complain_on_overflow */ bpf_elf_generic_reloc, /* special_function */ "R_BPF_64_ABS64", /* name */ - false, /* partial_inplace */ + true, /* partial_inplace */ 0, /* src_mask */ MINUS_ONE, /* dst_mask */ true) /* pcrel_offset */ @@ -103,7 +103,7 @@ complain_overflow_bitfield, /* complain_on_overflow */ bpf_elf_generic_reloc, /* special_function */ "R_BPF_64_NODYLD32", /* name */ - false, /* partial_inplace */ + true, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ true) /* pcrel_offset */ diff --git a/bfd/elf64-bpf.c b/bfd/elf64-bpf.c index 0bffe2c..c922a3e 100644 --- a/bfd/elf64-bpf.c +++ b/bfd/elf64-bpf.c @@ -385,8 +385,7 @@ elf64_bpf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) static bfd_reloc_status_type bpf_elf_generic_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, - void *data, asection *input_section, - bfd *output_bfd ATTRIBUTE_UNUSED, + void *data, asection *input_section, bfd *output_bfd, char **error_message ATTRIBUTE_UNUSED) { @@ -394,6 +393,22 @@ bpf_elf_generic_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, bfd_reloc_status_type status; bfd_byte *where; + /* From bfd_elf_generic_reloc. */ + 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 + && !reloc_entry->howto->pc_relative + && (symbol->section->flags & SEC_DEBUGGING) != 0 + && (input_section->flags & SEC_DEBUGGING) != 0) + reloc_entry->addend -= symbol->section->output_section->vma; + /* Sanity check that the address is in range. */ bfd_size_type end = bfd_get_section_limit_octets (abfd, input_section); bfd_size_type reloc_size; @@ -407,18 +422,15 @@ bpf_elf_generic_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, || end - reloc_entry->address < reloc_size) return bfd_reloc_outofrange; - /* Get the symbol value. */ - if (bfd_is_com_section (symbol->section)) - relocation = 0; - else - relocation = symbol->value; + /* Behave similarly to bfd_install_relocation with install_addend set. + That is, just install the addend and do not include the value of + the symbol. */ + relocation = reloc_entry->addend; if (symbol->flags & BSF_SECTION_SYM) /* Relocation against a section symbol: add in the section base address. */ relocation += BASEADDR (symbol->section); - relocation += reloc_entry->addend; - where = (bfd_byte *) data + reloc_entry->address; status = bfd_check_overflow (reloc_entry->howto->complain_on_overflow, @@ -449,8 +461,8 @@ bpf_elf_generic_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, where + reloc_entry->howto->bitpos / 8); } - reloc_entry->addend = relocation; - reloc_entry->address += input_section->output_offset; + if (output_bfd != NULL) + reloc_entry->address += input_section->output_offset; return bfd_reloc_ok; } |