summaryrefslogtreecommitdiff
path: root/bfd/elf.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2021-03-06 21:56:15 +1030
committerAlan Modra <amodra@gmail.com>2021-03-10 09:53:51 +1030
commit2dfa8341e079765f37ab02b2b63cfcffe64c37dd (patch)
tree410ec106436c5b04d0b74748fc9f6cb32bb65f09 /bfd/elf.c
parentccdc02ed07bbed9468c275a943fc5a970e949e99 (diff)
ELF DWARF in PE output
* elf.c (bfd_elf_generic_reloc): Make references between debug sections use section relative values.
Diffstat (limited to 'bfd/elf.c')
-rw-r--r--bfd/elf.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/bfd/elf.c b/bfd/elf.c
index 553fa65a11..35c31cf40b 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1302,8 +1302,7 @@ const char *const bfd_elf_section_type_names[] =
change anything about the way the reloc is handled, since it will
all be done at final link time. Rather than put special case code
into bfd_perform_relocation, all the reloc types use this howto
- function. It just short circuits the reloc if producing
- relocatable output against an external symbol. */
+ function, or should call this function for relocatable output. */
bfd_reloc_status_type
bfd_elf_generic_reloc (bfd *abfd ATTRIBUTE_UNUSED,
@@ -1323,6 +1322,20 @@ bfd_elf_generic_reloc (bfd *abfd ATTRIBUTE_UNUSED,
return bfd_reloc_ok;
}
+ /* In some cases the relocation should be treated as output section
+ relative, as when linking ELF DWARF into PE COFF. Many ELF
+ targets lack section relative relocations and instead use
+ ordinary absolute relocations for references between DWARF
+ sections. That is arguably a bug in those targets but it happens
+ to work for the usual case of linking to non-loaded ELF debug
+ sections with VMAs forced to zero. PE COFF on the other hand
+ doesn't allow a section VMA of zero. */
+ 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;
+
return bfd_reloc_continue;
}