aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2023-08-25 14:56:44 +0200
committerJan Beulich <jbeulich@suse.com>2023-08-25 14:56:44 +0200
commit67694446f772ae95d330419eb6d01e38e6d24612 (patch)
tree21119de766ad7554bd06371b5713ab4f58917c96 /bfd
parent183440b0aa1cd752c324a2f4c16a620bd938d9ad (diff)
downloadbinutils-67694446f772ae95d330419eb6d01e38e6d24612.zip
binutils-67694446f772ae95d330419eb6d01e38e6d24612.tar.gz
binutils-67694446f772ae95d330419eb6d01e38e6d24612.tar.bz2
bfd: correct relocation handling for objcopy COFF -> ELF
While documented to not be reliable, it is still odd for objcopy to silently produce bad output when converting COFF/PE object files to ELF ones. The issue there is that relocation addends all are screwed up by subtracting the symbol's section offset. In the COFF/PE world, to my knowledge, section contents stores the addends alone, not the result of symbol value plus addend. Hence the compensation talked about in a comment ahead of the sole use site of CALC_ADDEND() may need to account for the VMA (which is always zero for object files anyway), but not for the symbol value. The coff-sh.c adjustment is based upon guessing that behavior there is the same. Note also how coff-aarch64.c short-circuits CALC_ADDEND() altogether, which may suggest that a much simpler macro might do for the COFF_WITH_PE case in the three arch-specific files touched here. For (at least) Arm/WinCE this actually results in more appropriate objdump output as well, as can be seen in the one testcase which has its expectations adjusted (the generated binary doesn't change).
Diffstat (limited to 'bfd')
-rw-r--r--bfd/coff-i386.c3
-rw-r--r--bfd/coff-sh.c3
-rw-r--r--bfd/coff-x86_64.c3
-rw-r--r--bfd/coffcode.h9
4 files changed, 14 insertions, 4 deletions
diff --git a/bfd/coff-i386.c b/bfd/coff-i386.c
index 24a05d3..7151606 100644
--- a/bfd/coff-i386.c
+++ b/bfd/coff-i386.c
@@ -405,7 +405,8 @@ static reloc_howto_type howto_table[] =
cache_ptr->addend = - coffsym->native->u.syment.n_value; \
else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
&& ptr->section != (asection *) NULL) \
- cache_ptr->addend = - (ptr->section->vma + ptr->value); \
+ cache_ptr->addend = - (ptr->section->vma \
+ + COFF_PE_ADDEND_BIAS (ptr)); \
else \
cache_ptr->addend = 0; \
if (ptr && reloc.r_type < NUM_HOWTOS \
diff --git a/bfd/coff-sh.c b/bfd/coff-sh.c
index 14f502e..a20c011 100644
--- a/bfd/coff-sh.c
+++ b/bfd/coff-sh.c
@@ -544,7 +544,8 @@ sh_coff_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
cache_ptr->addend = 0; \
else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
&& ptr->section != (asection *) NULL) \
- cache_ptr->addend = - (ptr->section->vma + ptr->value); \
+ cache_ptr->addend = - (ptr->section->vma \
+ + COFF_PE_ADDEND_BIAS (ptr)); \
else \
cache_ptr->addend = 0; \
if ((reloc).r_type == R_SH_SWITCH8 \
diff --git a/bfd/coff-x86_64.c b/bfd/coff-x86_64.c
index 9a3f85c..57b975c 100644
--- a/bfd/coff-x86_64.c
+++ b/bfd/coff-x86_64.c
@@ -542,7 +542,8 @@ static reloc_howto_type howto_table[] =
cache_ptr->addend = - coffsym->native->u.syment.n_value; \
else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
&& ptr->section != NULL) \
- cache_ptr->addend = - (ptr->section->vma + ptr->value); \
+ cache_ptr->addend = - (ptr->section->vma \
+ + COFF_PE_ADDEND_BIAS (ptr)); \
else \
cache_ptr->addend = 0; \
if (ptr && reloc.r_type < NUM_HOWTOS \
diff --git a/bfd/coffcode.h b/bfd/coffcode.h
index e3f4afd..2792703 100644
--- a/bfd/coffcode.h
+++ b/bfd/coffcode.h
@@ -5192,6 +5192,12 @@ SUBSUBSECTION
final-linked object. See @code{CALC_ADDEND}.
*/
+#ifdef COFF_WITH_PE
+#define COFF_PE_ADDEND_BIAS(ptr) 0 /* Symbol value not stored in raw data. */
+#else
+#define COFF_PE_ADDEND_BIAS(ptr) ((ptr)->value)
+#endif
+
#ifndef CALC_ADDEND
#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
{ \
@@ -5208,7 +5214,8 @@ SUBSUBSECTION
cache_ptr->addend = 0; \
else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
&& ptr->section != NULL) \
- cache_ptr->addend = - (ptr->section->vma + ptr->value); \
+ cache_ptr->addend = - (ptr->section->vma \
+ + COFF_PE_ADDEND_BIAS (ptr)); \
else \
cache_ptr->addend = 0; \
}