132 lines
4.3 KiB
Diff
132 lines
4.3 KiB
Diff
We need this for libQt5WebEngine on i586. (bsc#1216908)
|
|
|
|
From 836654b1177ab305c36fe7319f08f0ad5d4fac1b Mon Sep 17 00:00:00 2001
|
|
From: Michael Matz <matz@suse.de>
|
|
Date: Tue, 7 Nov 2023 16:54:44 +0100
|
|
Subject: ld: Avoid overflows in string merging
|
|
To: binutils@sourceware.org
|
|
|
|
as the bug report shows we had an overflow in the test if
|
|
hash table resizing is needed. Reorder the expression to avoid
|
|
that. There's still a bug somewhere in gracefully handling
|
|
failure in resizing (e.g. out of memory), but this pushes the
|
|
boundary for that occurring somewhen into the future and
|
|
immediately helps the reporter.
|
|
|
|
bfd/
|
|
|
|
PR ld/31009
|
|
* merge.c (NEEDS_RESIZE): New macro avoiding overflow.
|
|
(sec_merge_maybe_resize): Use it.
|
|
(sec_merge_hash_insert): Ditto.
|
|
---
|
|
bfd/merge.c | 12 ++++++++----
|
|
1 file changed, 8 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/bfd/merge.c b/bfd/merge.c
|
|
index 722e6659486..61ffab4d706 100644
|
|
--- a/bfd/merge.c
|
|
+++ b/bfd/merge.c
|
|
@@ -94,6 +94,10 @@ struct sec_merge_hash
|
|
struct sec_merge_hash_entry **values;
|
|
};
|
|
|
|
+/* True when given NEWCOUNT and NBUCKETS indicate that the hash table needs
|
|
+ resizing. */
|
|
+#define NEEDS_RESIZE(newcount, nbuckets) ((newcount) > (nbuckets) / 3 * 2)
|
|
+
|
|
struct sec_merge_sec_info;
|
|
|
|
/* Information per merged blob. This is the unit of merging and is
|
|
@@ -167,7 +171,7 @@ static bool
|
|
sec_merge_maybe_resize (struct sec_merge_hash *table, unsigned added)
|
|
{
|
|
struct bfd_hash_table *bfdtab = &table->table;
|
|
- if (bfdtab->count + added > table->nbuckets * 2 / 3)
|
|
+ if (NEEDS_RESIZE (bfdtab->count + added, table->nbuckets))
|
|
{
|
|
unsigned i;
|
|
unsigned long newnb = table->nbuckets * 2;
|
|
@@ -175,7 +179,7 @@ sec_merge_maybe_resize (struct sec_merge_hash *table, unsigned added)
|
|
uint64_t *newl;
|
|
unsigned long alloc;
|
|
|
|
- while (bfdtab->count + added > newnb * 2 / 3)
|
|
+ while (NEEDS_RESIZE (bfdtab->count + added, newnb))
|
|
{
|
|
newnb *= 2;
|
|
if (!newnb)
|
|
@@ -239,8 +243,8 @@ sec_merge_hash_insert (struct sec_merge_hash *table,
|
|
hashp->alignment = 0;
|
|
hashp->u.suffix = NULL;
|
|
hashp->next = NULL;
|
|
- // We must not need resizing, otherwise _index is wrong
|
|
- BFD_ASSERT (bfdtab->count + 1 <= table->nbuckets * 2 / 3);
|
|
+ // We must not need resizing, otherwise the estimation was wrong
|
|
+ BFD_ASSERT (!NEEDS_RESIZE (bfdtab->count + 1, table->nbuckets));
|
|
bfdtab->count++;
|
|
table->key_lens[_index] = (hash << 32) | (uint32_t)len;
|
|
table->values[_index] = hashp;
|
|
--
|
|
2.42.0
|
|
|
|
|
|
From 21160d8a18dc21aafb8ab1026e13e5c524954a46 Mon Sep 17 00:00:00 2001
|
|
From: Michael Matz <matz@suse.de>
|
|
Date: Tue, 7 Nov 2023 17:12:46 +0100
|
|
Subject: bfd: use less memory in string merging
|
|
To: binutils@sourceware.org
|
|
|
|
the offset-to-entry mappings are allocated in blocks, which may
|
|
become a bit wasteful in case there are extremely many small
|
|
input files or sections. This made it so that a large project
|
|
(Qt5WebEngine) didn't build anymore on x86 32bit due to address
|
|
space limits. It barely fit into address space before the new
|
|
string merging, and then got pushed over the limit by this.
|
|
|
|
So instead of leaving the waste reallocate the maps to their final
|
|
size once known. Now the link barely fits again.
|
|
|
|
bfd/
|
|
* merge.c (record_section): Reallocate offset maps to their
|
|
final size.
|
|
---
|
|
bfd/merge.c | 14 ++++++++++++++
|
|
1 file changed, 14 insertions(+)
|
|
|
|
diff --git a/bfd/merge.c b/bfd/merge.c
|
|
index 61ffab4d706..eeaa1a01fe3 100644
|
|
--- a/bfd/merge.c
|
|
+++ b/bfd/merge.c
|
|
@@ -711,6 +711,7 @@ record_section (struct sec_merge_info *sinfo,
|
|
unsigned int align;
|
|
bfd_size_type amt;
|
|
bfd_byte *contents;
|
|
+ void *tmpptr;
|
|
|
|
amt = sec->size;
|
|
if (sec->flags & SEC_STRINGS)
|
|
@@ -771,6 +772,19 @@ record_section (struct sec_merge_info *sinfo,
|
|
|
|
free (contents);
|
|
contents = NULL;
|
|
+
|
|
+ /* We allocate the ofsmap arrays in blocks of 2048 elements.
|
|
+ In case we have very many small input files/sections,
|
|
+ this might waste large amounts of memory, so reallocate these
|
|
+ arrays here to their true size. */
|
|
+ amt = secinfo->noffsetmap + 1;
|
|
+ tmpptr = bfd_realloc (secinfo->map, amt * sizeof(secinfo->map[0]));
|
|
+ if (tmpptr)
|
|
+ secinfo->map = tmpptr;
|
|
+ tmpptr = bfd_realloc (secinfo->map_ofs, amt * sizeof(secinfo->map_ofs[0]));
|
|
+ if (tmpptr)
|
|
+ secinfo->map_ofs = tmpptr;
|
|
+
|
|
/*printf ("ZZZ %s:%s %u entries\n", sec->owner->filename, sec->name,
|
|
(unsigned)secinfo->noffsetmap);*/
|
|
|
|
--
|
|
2.42.0
|
|
|