vapier 15/08/27 17:35:33
Modified: README.history
Added:
50_all_binutils-2.25-stable-sort-for-ld-r-relocs.patch
51_all_binutils-2.25-dont-sort-ld-r-output-relocs-on-alpha.patch
Log:
fixes from upstream for ld reloc processing (including alpha) #558382 by Matt
Turner
Revision Changes Path
1.2 src/patchsets/binutils/2.25.1/README.history
file :
http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/binutils/2.25.1/README.history?rev=1.2&view=markup
plain:
http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/binutils/2.25.1/README.history?rev=1.2&content-type=text/plain
diff :
http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/binutils/2.25.1/README.history?r1=1.1&r2=1.2
Index: README.history
===================================================================
RCS file: /var/cvsroot/gentoo/src/patchsets/binutils/2.25.1/README.history,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- README.history 27 Jul 2015 03:26:42 -0000 1.1
+++ README.history 27 Aug 2015 17:35:33 -0000 1.2
@@ -1,3 +1,7 @@
+1.1 27 Aug 2015
+ + 50_all_binutils-2.25-stable-sort-for-ld-r-relocs.patch
+ + 51_all_binutils-2.25-dont-sort-ld-r-output-relocs-on-alpha.patch
+
1.0 27 Jul 2015
+ 12_all_sh-targets.patch
+ 20_all_gold-mips.patch
1.1
src/patchsets/binutils/2.25.1/50_all_binutils-2.25-stable-sort-for-ld-r-relocs.patch
file :
http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/binutils/2.25.1/50_all_binutils-2.25-stable-sort-for-ld-r-relocs.patch?rev=1.1&view=markup
plain:
http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/binutils/2.25.1/50_all_binutils-2.25-stable-sort-for-ld-r-relocs.patch?rev=1.1&content-type=text/plain
Index: 50_all_binutils-2.25-stable-sort-for-ld-r-relocs.patch
===================================================================
https://bugs.gentoo.org/558382
https://sourceware.org/bugzilla/show_bug.cgi?id=18867
>From 5fc980cc8be61203db24756e17d87f24c174f1ac Mon Sep 17 00:00:00 2001
From: Alan Modra <[email protected]>
Date: Wed, 26 Aug 2015 17:32:08 +0930
Subject: [PATCH 1/2] Use stable sort for ld -r relocs
A number of targets emit multiple relocs at a given r_offset, and
depend on those relocs staying in their original order.
PR 18867
* elflink.c (cmp_ext32l_r_offset, cmp_ext32b_r_offset): Delete.
(cmp_ext64l_r_offset, cmp_ext64b_r_offset): Delete.
(ext32l_r_offset, ext32b_r_offset, ext64l_r_offset, ext64b_r_offset):
New functions.
(elf_link_adjust_relocs): Use an insertion sort to sort relocs.
---
bfd/ChangeLog | 11 +++++
bfd/elflink.c | 149 ++++++++++++++++++++++++++++++----------------------------
2 files changed, 88 insertions(+), 72 deletions(-)
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 2c6b04b..6395d01 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -7961,10 +7961,12 @@ bfd_elf_perform_complex_relocation (bfd *input_bfd,
return r;
}
-/* qsort comparison functions sorting external relocs by r_offset. */
+/* Functions to read r_offset from external (target order) reloc
+ entry. Faster than bfd_getl32 et al, because we let the compiler
+ know the value is aligned. */
-static int
-cmp_ext32l_r_offset (const void *p, const void *q)
+static bfd_vma
+ext32l_r_offset (const void *p)
{
union aligned32
{
@@ -7972,27 +7974,17 @@ cmp_ext32l_r_offset (const void *p, const void *q)
unsigned char c[4];
};
const union aligned32 *a
- = (const union aligned32 *) ((const Elf32_External_Rel *) p)->r_offset;
- const union aligned32 *b
- = (const union aligned32 *) ((const Elf32_External_Rel *) q)->r_offset;
+ = (const union aligned32 *) &((const Elf32_External_Rel *) p)->r_offset;
uint32_t aval = ( (uint32_t) a->c[0]
| (uint32_t) a->c[1] << 8
| (uint32_t) a->c[2] << 16
| (uint32_t) a->c[3] << 24);
- uint32_t bval = ( (uint32_t) b->c[0]
- | (uint32_t) b->c[1] << 8
- | (uint32_t) b->c[2] << 16
- | (uint32_t) b->c[3] << 24);
- if (aval < bval)
- return -1;
- else if (aval > bval)
- return 1;
- return 0;
+ return aval;
}
-static int
-cmp_ext32b_r_offset (const void *p, const void *q)
+static bfd_vma
+ext32b_r_offset (const void *p)
{
union aligned32
{
@@ -8000,28 +7992,18 @@ cmp_ext32b_r_offset (const void *p, const void *q)
unsigned char c[4];
};
const union aligned32 *a
- = (const union aligned32 *) ((const Elf32_External_Rel *) p)->r_offset;
- const union aligned32 *b
- = (const union aligned32 *) ((const Elf32_External_Rel *) q)->r_offset;
+ = (const union aligned32 *) &((const Elf32_External_Rel *) p)->r_offset;
uint32_t aval = ( (uint32_t) a->c[0] << 24
| (uint32_t) a->c[1] << 16
| (uint32_t) a->c[2] << 8
| (uint32_t) a->c[3]);
- uint32_t bval = ( (uint32_t) b->c[0] << 24
- | (uint32_t) b->c[1] << 16
- | (uint32_t) b->c[2] << 8
- | (uint32_t) b->c[3]);
- if (aval < bval)
- return -1;
- else if (aval > bval)
- return 1;
- return 0;
+ return aval;
}
#ifdef BFD_HOST_64_BIT
-static int
-cmp_ext64l_r_offset (const void *p, const void *q)
+static bfd_vma
+ext64l_r_offset (const void *p)
{
union aligned64
{
@@ -8029,9 +8011,7 @@ cmp_ext64l_r_offset (const void *p, const void *q)
unsigned char c[8];
};
const union aligned64 *a
- = (const union aligned64 *) ((const Elf64_External_Rel *) p)->r_offset;
- const union aligned64 *b
- = (const union aligned64 *) ((const Elf64_External_Rel *) q)->r_offset;
+ = (const union aligned64 *) &((const Elf64_External_Rel *) p)->r_offset;
uint64_t aval = ( (uint64_t) a->c[0]
| (uint64_t) a->c[1] << 8
@@ -8041,23 +8021,11 @@ cmp_ext64l_r_offset (const void *p, const void *q)
| (uint64_t) a->c[5] << 40
| (uint64_t) a->c[6] << 48
| (uint64_t) a->c[7] << 56);
- uint64_t bval = ( (uint64_t) b->c[0]
- | (uint64_t) b->c[1] << 8
- | (uint64_t) b->c[2] << 16
- | (uint64_t) b->c[3] << 24
- | (uint64_t) b->c[4] << 32
- | (uint64_t) b->c[5] << 40
- | (uint64_t) b->c[6] << 48
- | (uint64_t) b->c[7] << 56);
- if (aval < bval)
- return -1;
- else if (aval > bval)
- return 1;
- return 0;
+ return aval;
}
-static int
-cmp_ext64b_r_offset (const void *p, const void *q)
+static bfd_vma
+ext64b_r_offset (const void *p)
{
union aligned64
{
@@ -8065,9 +8033,7 @@ cmp_ext64b_r_offset (const void *p, const void *q)
unsigned char c[8];
};
const union aligned64 *a
- = (const union aligned64 *) ((const Elf64_External_Rel *) p)->r_offset;
- const union aligned64 *b
- = (const union aligned64 *) ((const Elf64_External_Rel *) q)->r_offset;
+ = (const union aligned64 *) &((const Elf64_External_Rel *) p)->r_offset;
uint64_t aval = ( (uint64_t) a->c[0] << 56
| (uint64_t) a->c[1] << 48
@@ -8077,19 +8043,7 @@ cmp_ext64b_r_offset (const void *p, const void *q)
| (uint64_t) a->c[5] << 16
| (uint64_t) a->c[6] << 8
| (uint64_t) a->c[7]);
- uint64_t bval = ( (uint64_t) b->c[0] << 56
- | (uint64_t) b->c[1] << 48
- | (uint64_t) b->c[2] << 40
- | (uint64_t) b->c[3] << 32
- | (uint64_t) b->c[4] << 24
- | (uint64_t) b->c[5] << 16
- | (uint64_t) b->c[6] << 8
- | (uint64_t) b->c[7]);
- if (aval < bval)
- return -1;
- else if (aval > bval)
- return 1;
- return 0;
+ return aval;
}
#endif
@@ -8158,16 +8112,20 @@ elf_link_adjust_relocs (bfd *abfd,
(*swap_out) (abfd, irela, erela);
}
- if (sort)
+ if (sort && count != 0)
{
- int (*compare) (const void *, const void *);
+ bfd_vma (*ext_r_off) (const void *);
+ bfd_vma r_off;
+ size_t elt_size;
+ bfd_byte *base, *end, *p, *loc;
+ bfd_byte buf[sizeof (Elf64_External_Rela)];
if (bed->s->arch_size == 32)
{
if (abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE)
- compare = cmp_ext32l_r_offset;
+ ext_r_off = ext32l_r_offset;
else if (abfd->xvec->header_byteorder == BFD_ENDIAN_BIG)
- compare = cmp_ext32b_r_offset;
+ ext_r_off = ext32b_r_offset;
else
abort ();
}
@@ -8175,14 +8133,61 @@ elf_link_adjust_relocs (bfd *abfd,
{
#ifdef BFD_HOST_64_BIT
if (abfd->xvec->header_byteorder == BFD_ENDIAN_LITTLE)
- compare = cmp_ext64l_r_offset;
+ ext_r_off = ext64l_r_offset;
else if (abfd->xvec->header_byteorder == BFD_ENDIAN_BIG)
- compare = cmp_ext64b_r_offset;
+ ext_r_off = ext64b_r_offset;
else
#endif
abort ();
}
- qsort (reldata->hdr->contents, count, reldata->hdr->sh_entsize, compare);
+
+ /* Must use a stable sort here. Insertion sort, since the
+ relocs are mostly sorted already. */
+ elt_size = reldata->hdr->sh_entsize;
+ base = reldata->hdr->contents;
+ end = base + count * elt_size;
+ if (elt_size > sizeof (buf))
+ abort ();
+
+ /* Ensure the first element is lowest. This acts as a sentinel,
+ speeding the main loop below. */
+ r_off = (*ext_r_off) (base);
+ for (p = loc = base; (p += elt_size) < end; )
+ {
+ bfd_vma r_off2 = (*ext_r_off) (p);
+ if (r_off > r_off2)
+ {
+ r_off = r_off2;
+ loc = p;
+ }
+ }
+ if (loc != base)
+ {
+ /* Don't just swap *base and *loc as that changes the order
+ of the original base[0] and base[1] if they happen to
+ have the same r_offset. */
+ memcpy (buf, loc, elt_size);
+ memmove (base + elt_size, base, loc - base);
+ memcpy (base, buf, elt_size);
+ }
+
+ for (p = base + elt_size; (p += elt_size) < end; )
+ {
+ /* base to p is sorted, *p is next to insert. */
+ r_off = (*ext_r_off) (p);
+ /* Search the sorted region for location to insert. */
+ loc = p - elt_size;
+ while (r_off < (*ext_r_off) (loc))
+ loc -= elt_size;
+ loc += elt_size;
+ if (loc != p)
+ {
+ memcpy (buf, p, elt_size);
+ memmove (loc + elt_size, loc, p - loc);
+ memcpy (loc, buf, elt_size);
+ }
+ }
+ /* Hashes are no longer valid. */
free (reldata->hashes);
reldata->hashes = NULL;
}
--
2.4.4
1.1
src/patchsets/binutils/2.25.1/51_all_binutils-2.25-dont-sort-ld-r-output-relocs-on-alpha.patch
file :
http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/binutils/2.25.1/51_all_binutils-2.25-dont-sort-ld-r-output-relocs-on-alpha.patch?rev=1.1&view=markup
plain:
http://sources.gentoo.org/viewvc.cgi/gentoo/src/patchsets/binutils/2.25.1/51_all_binutils-2.25-dont-sort-ld-r-output-relocs-on-alpha.patch?rev=1.1&content-type=text/plain
Index: 51_all_binutils-2.25-dont-sort-ld-r-output-relocs-on-alpha.patch
===================================================================
https://bugs.gentoo.org/558382
https://sourceware.org/bugzilla/show_bug.cgi?id=18867
>From 00b2b5c400e542a436b66989841a2f3b81181e91 Mon Sep 17 00:00:00 2001
From: Alan Modra <[email protected]>
Date: Thu, 27 Aug 2015 10:54:28 +0930
Subject: [PATCH 2/2] Don't sort ld -r output relocs on alpha
LITERAL/LITUSE relocs must be kept together.
PR 18867
* elf64-alpha.c (elf64_alpha_sort_relocs_p): New function.
(elf_backend_sort_relocs_p): Define.
---
bfd/ChangeLog | 5 +++++
bfd/elf64-alpha.c | 14 ++++++++++++++
2 files changed, 19 insertions(+)
diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c
index 8f8cf7b..094a0b9 100644
--- a/bfd/elf64-alpha.c
+++ b/bfd/elf64-alpha.c
@@ -1757,6 +1757,18 @@ elf64_alpha_want_plt (struct alpha_elf_link_hash_entry
*ah)
&& (ah->flags & ~ALPHA_ELF_LINK_HASH_LU_PLT) == 0);
}
+/* Whether to sort relocs output by ld -r or ld --emit-relocs, by r_offset.
+ Don't do so for code sections. We want to keep ordering of LITERAL/LITUSE
+ as is. On the other hand, elf-eh-frame.c processing requires .eh_frame
+ relocs to be sorted. */
+
+static bfd_boolean
+elf64_alpha_sort_relocs_p (asection *sec)
+{
+ return (sec->flags & SEC_CODE) == 0;
+}
+
+
/* Handle dynamic relocations when doing an Alpha ELF link. */
static bfd_boolean
@@ -5518,6 +5530,8 @@ static const struct elf_size_info alpha_elf_size_info =
elf64_alpha_add_symbol_hook
#define elf_backend_relocs_compatible \
_bfd_elf_relocs_compatible
+#define elf_backend_sort_relocs_p \
+ elf64_alpha_sort_relocs_p
#define elf_backend_check_relocs \
elf64_alpha_check_relocs
#define elf_backend_create_dynamic_sections \
--
2.4.4