aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2014-04-11 16:02:52 +0100
committerNick Clifton <nickc@redhat.com>2014-04-11 16:02:52 +0100
commit32ae0d80cd430150ad9536aa160f34f504e129bc (patch)
tree76b9dab3571164bcc1e07302277c471a07ae7f68 /bfd
parent58a84dcf29b735ee776536b4c51ba90b51612b71 (diff)
downloadfsf-binutils-gdb-32ae0d80cd430150ad9536aa160f34f504e129bc.zip
fsf-binutils-gdb-32ae0d80cd430150ad9536aa160f34f504e129bc.tar.gz
fsf-binutils-gdb-32ae0d80cd430150ad9536aa160f34f504e129bc.tar.bz2
PE32+ binaries that use addresses > 1^32 have a problem in that the linker
converts some address expressions into absolute values, but the PE format only stores absolutes as 32-bits. This is a partial solution which attempts to convert such absolute values back to section relative ones instead. It fails for symbols like __image_base and ImageBase__, but it is unclear as to whether these values are ever actually used by applications. PR ld/16821 * peXXigen.c (abs_finder): New function. (_bfd_XXi_swap_sym_out): For absolute symbols with values larger than 1^32 try to convert them into section relative values instead.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog8
-rw-r--r--bfd/peXXigen.c31
2 files changed, 39 insertions, 0 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 79d32c7..7621c6f 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,13 @@
2014-04-11 Nick Clifton <nickc@redhat.com>
+ PR ld/16821
+ * peXXigen.c (abs_finder): New function.
+ (_bfd_XXi_swap_sym_out): For absolute symbols with values larger
+ than 1^32 try to convert them into section relative values
+ instead.
+
+2014-04-11 Nick Clifton <nickc@redhat.com>
+
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c
index ea7846f..36d90cc 100644
--- a/bfd/peXXigen.c
+++ b/bfd/peXXigen.c
@@ -207,6 +207,14 @@ _bfd_XXi_swap_sym_in (bfd * abfd, void * ext1, void * in1)
#endif
}
+static bfd_boolean
+abs_finder (bfd * abfd ATTRIBUTE_UNUSED, asection * sec, void * data)
+{
+ bfd_vma abs_val = * (bfd_vma *) data;
+
+ return (sec->vma <= abs_val) && ((sec->vma + (1L << 32)) > abs_val);
+}
+
unsigned int
_bfd_XXi_swap_sym_out (bfd * abfd, void * inp, void * extp)
{
@@ -221,6 +229,29 @@ _bfd_XXi_swap_sym_out (bfd * abfd, void * inp, void * extp)
else
memcpy (ext->e.e_name, in->_n._n_name, SYMNMLEN);
+ /* The PE32 and PE32+ formats only use 4 bytes to hold the value of a
+ symbol. This is a problem on 64-bit targets where we can generate
+ absolute symbols with values >= 1^32. We try to work around this
+ problem by finding a section whose base address is sufficient to
+ reduce the absolute value to < 1^32, and then transforming the
+ symbol into a section relative symbol. This of course is a hack. */
+ if (sizeof (in->n_value) > 4
+ && in->n_value > ((1L << 32) - 1)
+ && in->n_scnum == -1)
+ {
+ asection * sec;
+
+ sec = bfd_sections_find_if (abfd, abs_finder, & in->n_value);
+ if (sec)
+ {
+ in->n_value -= sec->vma;
+ in->n_scnum = sec->target_index;
+ }
+ /* else: FIXME: The value is outside the range of any section. This
+ happens for __image_base__ and __ImageBase__ and maybe some other
+ symbols as well. We should find a way to handle these values. */
+ }
+
H_PUT_32 (abfd, in->n_value, ext->e_value);
H_PUT_16 (abfd, in->n_scnum, ext->e_scnum);