summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--system/binutils/APKBUILD10
-rw-r--r--system/binutils/memory.patch449
2 files changed, 455 insertions, 4 deletions
diff --git a/system/binutils/APKBUILD b/system/binutils/APKBUILD
index d8fc3e7c5..4cd3901ec 100644
--- a/system/binutils/APKBUILD
+++ b/system/binutils/APKBUILD
@@ -1,7 +1,7 @@
# Maintainer: Adelie Platform Group <adelie-devel@lists.adelielinux.org>
pkgname=binutils
pkgver=2.31.1
-pkgrel=0
+pkgrel=1
pkgdesc="Tools necessary to build programs"
url="http://www.gnu.org/software/binutils/"
depends=""
@@ -47,9 +47,11 @@ build() {
_cross_configure="--disable-install-libiberty"
fi
- if [ "$CTARGET_ARCH" = "x86_64" ]; then
- _arch_configure="--enable-targets=x86_64-pep"
- fi
+ # -z separate-code is currently causing kernel miscompiles on x86*
+ case "$CTARGET_ARCH" in
+ x86 | pmmx | i528) _arch_configure="--disable-separate-code" ;;
+ x86_64) _arch_configure="--disable-separate-code --enable-targets=x86_64-pep" ;;
+ esac
case "$CTARGET_ARCH" in
mips*) _hash_style_configure="--enable-default-hash-style=sysv" ;;
diff --git a/system/binutils/memory.patch b/system/binutils/memory.patch
new file mode 100644
index 000000000..f2cfea130
--- /dev/null
+++ b/system/binutils/memory.patch
@@ -0,0 +1,449 @@
+From 9999de060bbcc7cca9dce213deeeec6593887a8e Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Tue, 27 Feb 2018 12:22:58 -0800
+Subject: [PATCH] Limit memory size to half of address space
+
+When link_info.keep_memory is TRUE, linker caches the relocation
+information and symbol tables of input files in memory. On 32-bit
+hosts, linker runs out of 32-bit virtual memory on input files with many
+relocations. This patch limits the allocated memory size to half of
+the address space for 32-bit hosts.
+
+bfd/
+
+ PR ld/18028
+ * bfd-in.h (_bfd_link_keep_memory): New.
+ * bfd-in2.h: Regenerated.
+ * bfd.c (bfd): Add alloc_size.
+ * elf-bfd.h (_bfd_elf_link_info_read_relocs): New.
+ * elf32-i386.c (elf_i386_check_relocs): Use _bfd_link_keep_memory.
+ Update cache_size.
+ * elf64-x86-64.c (elf_x86_64_check_relocs): Likewise.
+ * elflink.c (_bfd_elf_link_read_relocs): Renamed to ...
+ (_bfd_elf_link_info_read_relocs): This. Update cache_size.
+ (_bfd_elf_link_read_relocs): New.
+ (_bfd_elf_link_check_relocs): Call _bfd_elf_link_info_read_relocs
+ instead of _bfd_elf_link_read_relocs.
+ (elf_link_add_object_symbols): Likewise.
+ (elf_link_input_bfd): Likewise.
+ (init_reloc_cookie_rels): Likewise.
+ (init_reloc_cookie): Update cache_size. Call
+ _bfd_elf_link_info_read_relocs instead of
+ _bfd_elf_link_read_relocs.
+ (link_info_ok): New.
+ (elf_gc_smash_unused_vtentry_relocs): Updated. Call
+ _bfd_elf_link_info_read_relocs instead of
+ _bfd_elf_link_read_relocs.
+ (bfd_elf_gc_sections): Use link_info_ok. Pass &link_info_ok
+ to elf_gc_smash_unused_vtentry_relocs.
+ * linker.c (_bfd_link_keep_memory): New.
+ * opncls.c (bfd_alloc): Update alloc_size.
+
+include/
+
+ PR ld/18028
+ * bfdlink.h (bfd_link_info): Add cache_size and max_alloc_size.
+
+ld/
+
+ PR ld/18028
+ * ldmain.c: Include "bfd_stdint.h".
+ (main): Set link_info.max_alloc_size to half of the address space.
+---
+ bfd/bfd-in.h | 2 ++
+ bfd/bfd-in2.h | 5 +++
+ bfd/bfd.c | 3 ++
+ bfd/elf-bfd.h | 3 ++
+ bfd/elf32-i386.c | 3 +-
+ bfd/elf64-x86-64.c | 3 +-
+ bfd/elflink.c | 89 ++++++++++++++++++++++++++++++++++++++++--------------
+ bfd/linker.c | 33 ++++++++++++++++++++
+ bfd/opncls.c | 2 ++
+ include/bfdlink.h | 7 +++++
+ ld/ldmain.c | 3 ++
+ 11 files changed, 128 insertions(+), 25 deletions(-)
+
+diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
+index a06cd740c0..ca4bec8aab 100644
+--- a/bfd/bfd-in.h
++++ b/bfd/bfd-in.h
+@@ -600,6 +600,8 @@ struct bfd_section_already_linked;
+ struct bfd_elf_version_tree;
+ #endif
+
++extern bfd_boolean _bfd_link_keep_memory (struct bfd_link_info *);
++
+ extern bfd_boolean bfd_section_already_linked_table_init (void);
+ extern void bfd_section_already_linked_table_free (void);
+ extern bfd_boolean _bfd_handle_already_linked
+diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
+index 9742c1ac7f..0794bcdcdb 100644
+--- a/bfd/bfd-in2.h
++++ b/bfd/bfd-in2.h
+@@ -607,6 +607,8 @@ struct bfd_section_already_linked;
+ struct bfd_elf_version_tree;
+ #endif
+
++extern bfd_boolean _bfd_link_keep_memory (struct bfd_link_info *);
++
+ extern bfd_boolean bfd_section_already_linked_table_init (void);
+ extern void bfd_section_already_linked_table_free (void);
+ extern bfd_boolean _bfd_handle_already_linked
+@@ -6989,6 +6991,9 @@ struct bfd
+ be used only for archive elements. */
+ int archive_pass;
+
++ /* The total size of memory from bfd_alloc. */
++ bfd_size_type alloc_size;
++
+ /* Stuff only useful for object files:
+ The start address. */
+ bfd_vma start_address;
+diff --git a/bfd/bfd.c b/bfd/bfd.c
+index 288b5b14fe..182b544662 100644
+--- a/bfd/bfd.c
++++ b/bfd/bfd.c
+@@ -267,6 +267,9 @@ CODE_FRAGMENT
+ . be used only for archive elements. *}
+ . int archive_pass;
+ .
++. {* The total size of memory from bfd_alloc. *}
++. bfd_size_type alloc_size;
++.
+ . {* Stuff only useful for object files:
+ . The start address. *}
+ . bfd_vma start_address;
+diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
+index afd6982a92..37a7b07e51 100644
+--- a/bfd/elf-bfd.h
++++ b/bfd/elf-bfd.h
+@@ -2294,6 +2294,9 @@ extern char *_bfd_elfcore_strndup
+
+ extern Elf_Internal_Rela *_bfd_elf_link_read_relocs
+ (bfd *, asection *, void *, Elf_Internal_Rela *, bfd_boolean);
++extern Elf_Internal_Rela *_bfd_elf_link_info_read_relocs
++ (bfd *, struct bfd_link_info *, asection *, void *, Elf_Internal_Rela *,
++ bfd_boolean);
+
+ extern bfd_boolean _bfd_elf_link_output_relocs
+ (bfd *, asection *, Elf_Internal_Shdr *, Elf_Internal_Rela *,
+diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
+index 61a14097b0..9a781dc089 100644
+--- a/bfd/elf32-i386.c
++++ b/bfd/elf32-i386.c
+@@ -1909,13 +1909,14 @@ elf_i386_check_relocs (bfd *abfd,
+
+ if (elf_section_data (sec)->this_hdr.contents != contents)
+ {
+- if (!converted && !info->keep_memory)
++ if (!converted && !_bfd_link_keep_memory (info))
+ free (contents);
+ else
+ {
+ /* Cache the section contents for elf_link_input_bfd if any
+ load is converted or --no-keep-memory isn't used. */
+ elf_section_data (sec)->this_hdr.contents = contents;
++ info->cache_size += sec->size;
+ }
+ }
+
+diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
+index 7016964ace..4ba15ec9fa 100644
+--- a/bfd/elf64-x86-64.c
++++ b/bfd/elf64-x86-64.c
+@@ -2281,13 +2281,14 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
+
+ if (elf_section_data (sec)->this_hdr.contents != contents)
+ {
+- if (!converted && !info->keep_memory)
++ if (!converted && !_bfd_link_keep_memory (info))
+ free (contents);
+ else
+ {
+ /* Cache the section contents for elf_link_input_bfd if any
+ load is converted or --no-keep-memory isn't used. */
+ elf_section_data (sec)->this_hdr.contents = contents;
++ info->cache_size += sec->size;
+ }
+ }
+
+diff --git a/bfd/elflink.c b/bfd/elflink.c
+index 092edaea26..831605b80a 100644
+--- a/bfd/elflink.c
++++ b/bfd/elflink.c
+@@ -2475,14 +2475,16 @@ elf_link_read_relocs_from_section (bfd *abfd,
+ according to the KEEP_MEMORY argument. If O has two relocation
+ sections (both REL and RELA relocations), then the REL_HDR
+ relocations will appear first in INTERNAL_RELOCS, followed by the
+- RELA_HDR relocations. */
++ RELA_HDR relocations. If INFO isn't NULL and KEEP_MEMORY is TRUE,
++ update cache_size. */
+
+ Elf_Internal_Rela *
+-_bfd_elf_link_read_relocs (bfd *abfd,
+- asection *o,
+- void *external_relocs,
+- Elf_Internal_Rela *internal_relocs,
+- bfd_boolean keep_memory)
++_bfd_elf_link_info_read_relocs (bfd *abfd,
++ struct bfd_link_info *info,
++ asection *o,
++ void *external_relocs,
++ Elf_Internal_Rela *internal_relocs,
++ bfd_boolean keep_memory)
+ {
+ void *alloc1 = NULL;
+ Elf_Internal_Rela *alloc2 = NULL;
+@@ -2502,7 +2504,11 @@ _bfd_elf_link_read_relocs (bfd *abfd,
+
+ size = (bfd_size_type) o->reloc_count * sizeof (Elf_Internal_Rela);
+ if (keep_memory)
+- internal_relocs = alloc2 = (Elf_Internal_Rela *) bfd_alloc (abfd, size);
++ {
++ internal_relocs = alloc2 = (Elf_Internal_Rela *) bfd_alloc (abfd, size);
++ if (info)
++ info->cache_size += size;
++ }
+ else
+ internal_relocs = alloc2 = (Elf_Internal_Rela *) bfd_malloc (size);
+ if (internal_relocs == NULL)
+@@ -2568,6 +2574,22 @@ _bfd_elf_link_read_relocs (bfd *abfd,
+ return NULL;
+ }
+
++/* This is similar to _bfd_elf_link_info_read_relocs, except for that
++ NULL is passed to _bfd_elf_link_info_read_relocs for pointer to
++ struct bfd_link_info. */
++
++Elf_Internal_Rela *
++_bfd_elf_link_read_relocs (bfd *abfd,
++ asection *o,
++ void *external_relocs,
++ Elf_Internal_Rela *internal_relocs,
++ bfd_boolean keep_memory)
++{
++ return _bfd_elf_link_info_read_relocs (abfd, NULL, o, external_relocs,
++ internal_relocs, keep_memory);
++
++}
++
+ /* Compute the size of, and allocate space for, REL_HDR which is the
+ section header for a section containing relocations for O. */
+
+@@ -3736,8 +3758,10 @@ _bfd_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
+ || bfd_is_abs_section (o->output_section))
+ continue;
+
+- internal_relocs = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL,
+- info->keep_memory);
++ internal_relocs = _bfd_elf_link_info_read_relocs (abfd, info,
++ o, NULL,
++ NULL,
++ _bfd_link_keep_memory (info));
+ if (internal_relocs == NULL)
+ return FALSE;
+
+@@ -4990,9 +5014,10 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
+ && (s->flags & SEC_DEBUGGING) != 0))
+ continue;
+
+- internal_relocs = _bfd_elf_link_read_relocs (abfd, s, NULL,
+- NULL,
+- info->keep_memory);
++ internal_relocs = _bfd_elf_link_info_read_relocs (abfd, info,
++ s, NULL,
++ NULL,
++ _bfd_link_keep_memory (info));
+ if (internal_relocs == NULL)
+ goto error_free_vers;
+
+@@ -10518,8 +10543,10 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
+
+ /* Get the swapped relocs. */
+ internal_relocs
+- = _bfd_elf_link_read_relocs (input_bfd, o, flinfo->external_relocs,
+- flinfo->internal_relocs, FALSE);
++ = _bfd_elf_link_info_read_relocs (input_bfd, flinfo->info, o,
++ flinfo->external_relocs,
++ flinfo->internal_relocs,
++ FALSE);
+ if (internal_relocs == NULL
+ && o->reloc_count > 0)
+ return FALSE;
+@@ -12684,8 +12711,12 @@ init_reloc_cookie (struct elf_reloc_cookie *cookie,
+ info->callbacks->einfo (_("%P%X: can not read symbols: %E\n"));
+ return FALSE;
+ }
+- if (info->keep_memory)
+- symtab_hdr->contents = (bfd_byte *) cookie->locsyms;
++ if (_bfd_link_keep_memory (info) )
++ {
++ symtab_hdr->contents = (bfd_byte *) cookie->locsyms;
++ info->cache_size += (cookie->locsymcount
++ * sizeof (Elf_External_Sym_Shndx));
++ }
+ }
+ return TRUE;
+ }
+@@ -12718,8 +12749,9 @@ init_reloc_cookie_rels (struct elf_reloc_cookie *cookie,
+ }
+ else
+ {
+- cookie->rels = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
+- info->keep_memory);
++ cookie->rels = _bfd_elf_link_info_read_relocs (abfd, info, sec,
++ NULL, NULL,
++ _bfd_link_keep_memory (info));
+ if (cookie->rels == NULL)
+ return FALSE;
+ cookie->rel = cookie->rels;
+@@ -13233,14 +13265,21 @@ elf_gc_propagate_vtable_entries_used (struct elf_link_hash_entry *h, void *okp)
+ return TRUE;
+ }
+
++struct link_info_ok
++{
++ struct bfd_link_info *info;
++ bfd_boolean ok;
++};
++
+ static bfd_boolean
+-elf_gc_smash_unused_vtentry_relocs (struct elf_link_hash_entry *h, void *okp)
++elf_gc_smash_unused_vtentry_relocs (struct elf_link_hash_entry *h, void *ptr)
+ {
+ asection *sec;
+ bfd_vma hstart, hend;
+ Elf_Internal_Rela *relstart, *relend, *rel;
+ const struct elf_backend_data *bed;
+ unsigned int log_file_align;
++ struct link_info_ok *info = (struct link_info_ok *) ptr;
+
+ /* Take care of both those symbols that do not describe vtables as
+ well as those that are not loaded. */
+@@ -13256,9 +13295,10 @@ elf_gc_smash_unused_vtentry_relocs (struct elf_link_hash_entry *h, void *okp)
+ hstart = h->root.u.def.value;
+ hend = hstart + h->size;
+
+- relstart = _bfd_elf_link_read_relocs (sec->owner, sec, NULL, NULL, TRUE);
++ relstart = _bfd_elf_link_info_read_relocs (sec->owner, info->info,
++ sec, NULL, NULL, TRUE);
+ if (!relstart)
+- return *(bfd_boolean *) okp = FALSE;
++ return info->ok = FALSE;
+ bed = get_elf_backend_data (sec->owner);
+ log_file_align = bed->s->log_file_align;
+
+@@ -13379,6 +13419,7 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
+ elf_gc_mark_hook_fn gc_mark_hook;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ struct elf_link_hash_table *htab;
++ struct link_info_ok info_ok;
+
+ if (!bed->can_gc_sections
+ || !is_elf_hash_table (info->hash))
+@@ -13420,8 +13461,10 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
+ return FALSE;
+
+ /* Kill the vtable relocations that were not used. */
+- elf_link_hash_traverse (htab, elf_gc_smash_unused_vtentry_relocs, &ok);
+- if (!ok)
++ info_ok.info = info;
++ info_ok.ok = TRUE;
++ elf_link_hash_traverse (htab, elf_gc_smash_unused_vtentry_relocs, &info_ok);
++ if (!info_ok.ok)
+ return FALSE;
+
+ /* Mark dynamically referenced symbols. */
+diff --git a/bfd/linker.c b/bfd/linker.c
+index c29a6e7e10..909d768552 100644
+--- a/bfd/linker.c
++++ b/bfd/linker.c
+@@ -3471,3 +3471,36 @@ _bfd_nolink_bfd_define_start_stop (struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ {
+ return (struct bfd_link_hash_entry *) _bfd_ptr_bfd_null_error (sec->owner);
+ }
++
++bfd_boolean
++_bfd_link_keep_memory (struct bfd_link_info * info)
++{
++ bfd *abfd;
++ bfd_size_type size;
++
++ if (!info->keep_memory)
++ return FALSE;
++
++ /* Keep allocated memory size below limit only for 32-bit hosts. */
++ if (sizeof (void *) > 4)
++ return TRUE;
++
++ abfd = info->input_bfds;
++ size = info->cache_size;
++ do
++ {
++ if (size >= info->max_alloc_size)
++ {
++ /* Over the limit. Reduce the memory usage. */
++ info->keep_memory = FALSE;
++ return FALSE;
++ }
++ if (!abfd)
++ break;
++ size += abfd->alloc_size;
++ abfd = abfd->link.next;
++ }
++ while (1);
++
++ return TRUE;
++}
+diff --git a/bfd/opncls.c b/bfd/opncls.c
+index 16b568c8ab..86262e1231 100644
+--- a/bfd/opncls.c
++++ b/bfd/opncls.c
+@@ -949,6 +949,8 @@ bfd_alloc (bfd *abfd, bfd_size_type size)
+ ret = objalloc_alloc ((struct objalloc *) abfd->memory, ul_size);
+ if (ret == NULL)
+ bfd_set_error (bfd_error_no_memory);
++ else
++ abfd->alloc_size += size;
+ return ret;
+ }
+
+diff --git a/include/bfdlink.h b/include/bfdlink.h
+index 5d637acbab..f06d5171c3 100644
+--- a/include/bfdlink.h
++++ b/include/bfdlink.h
+@@ -635,6 +635,13 @@ struct bfd_link_info
+
+ /* The version information. */
+ struct bfd_elf_version_tree *version_info;
++
++ /* Size of cache. Backend can use it to keep strace cache size. */
++ bfd_size_type cache_size;
++
++ /* The maximum size of allocated memory. Backend can use cache_size
++ and and max_alloc_size to decide if keep_memory should be honored. */
++ bfd_size_type max_alloc_size;
+ };
+
+ /* This structures holds a set of callback functions. These are called
+diff --git a/ld/ldmain.c b/ld/ldmain.c
+index b6914db5da..14c3349c97 100644
+--- a/ld/ldmain.c
++++ b/ld/ldmain.c
+@@ -21,6 +21,7 @@
+
+ #include "sysdep.h"
+ #include "bfd.h"
++#include "bfd_stdint.h"
+ #include "safe-ctype.h"
+ #include "libiberty.h"
+ #include "progress.h"
+@@ -271,6 +272,8 @@ main (int argc, char **argv)
+
+ link_info.allow_undefined_version = TRUE;
+ link_info.keep_memory = TRUE;
++ /* Limit the allocated memory size to half of the address space. */
++ link_info.max_alloc_size = ((uintptr_t) (void *) -1) / 2;
+ link_info.combreloc = TRUE;
+ link_info.strip_discarded = TRUE;
+ link_info.emit_hash = DEFAULT_EMIT_SYSV_HASH;