binutils/binutils-use-less-memory.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