@@ -13621,7 +13621,8 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
static bool
init_reloc_cookie (struct elf_reloc_cookie *cookie,
- struct bfd_link_info *info, bfd *abfd)
+ struct bfd_link_info *info, bfd *abfd,
+ bool keep_memory)
{
Elf_Internal_Shdr *symtab_hdr;
const struct elf_backend_data *bed;
@@ -13659,7 +13660,7 @@ init_reloc_cookie (struct elf_reloc_cookie *cookie,
info->callbacks->einfo (_("%P%X: can not read symbols: %E\n"));
return false;
}
- if (_bfd_elf_link_keep_memory (info) )
+ if (keep_memory || _bfd_elf_link_keep_memory (info))
{
symtab_hdr->contents = (bfd_byte *) cookie->locsyms;
info->cache_size += (cookie->locsymcount
@@ -13687,7 +13688,7 @@ fini_reloc_cookie (struct elf_reloc_cookie *cookie, bfd *abfd)
static bool
init_reloc_cookie_rels (struct elf_reloc_cookie *cookie,
struct bfd_link_info *info, bfd *abfd,
- asection *sec)
+ asection *sec, bool keep_memory)
{
if (sec->reloc_count == 0)
{
@@ -13698,7 +13699,7 @@ init_reloc_cookie_rels (struct elf_reloc_cookie *cookie,
{
cookie->rels = _bfd_elf_link_info_read_relocs
(abfd, info, sec, NULL, NULL,
- _bfd_elf_link_keep_memory (info));
+ keep_memory || _bfd_elf_link_keep_memory (info));
if (cookie->rels == NULL)
return false;
cookie->rel = cookie->rels;
@@ -13724,11 +13725,12 @@ fini_reloc_cookie_rels (struct elf_reloc_cookie *cookie,
static bool
init_reloc_cookie_for_section (struct elf_reloc_cookie *cookie,
struct bfd_link_info *info,
- asection *sec)
+ asection *sec, bool keep_memory)
{
- if (!init_reloc_cookie (cookie, info, sec->owner))
+ if (!init_reloc_cookie (cookie, info, sec->owner, keep_memory))
goto error1;
- if (!init_reloc_cookie_rels (cookie, info, sec->owner, sec))
+ if (!init_reloc_cookie_rels (cookie, info, sec->owner, sec,
+ keep_memory))
goto error2;
return true;
@@ -13939,7 +13941,7 @@ _bfd_elf_gc_mark (struct bfd_link_info *info,
{
struct elf_reloc_cookie cookie;
- if (!init_reloc_cookie_for_section (&cookie, info, sec))
+ if (!init_reloc_cookie_for_section (&cookie, info, sec, false))
ret = false;
else
{
@@ -13957,7 +13959,14 @@ _bfd_elf_gc_mark (struct bfd_link_info *info,
{
struct elf_reloc_cookie cookie;
- if (!init_reloc_cookie_for_section (&cookie, info, eh_frame))
+ /* NB: When --no-keep-memory is used, the symbol table and
+ relocation info for eh_frame are freed after they are retrieved
+ for each text section in the input object. If an input object
+ has many text sections, the same data is retrieved and freed
+ many times which can take a very long time. Always keep the
+ symbol table and relocation info for eh_frame to avoid it. */
+ if (!init_reloc_cookie_for_section (&cookie, info, eh_frame,
+ true))
ret = false;
else
{
@@ -14397,13 +14406,14 @@ bfd_elf_parse_eh_frame_entries (bfd *abfd ATTRIBUTE_UNUSED,
if (sec == NULL || sec->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
continue;
- if (!init_reloc_cookie (&cookie, info, ibfd))
+ if (!init_reloc_cookie (&cookie, info, ibfd, false))
return false;
for (sec = ibfd->sections; sec; sec = sec->next)
{
if (startswith (bfd_section_name (sec), ".eh_frame_entry")
- && init_reloc_cookie_rels (&cookie, info, ibfd, sec))
+ && init_reloc_cookie_rels (&cookie, info, ibfd, sec,
+ false))
{
_bfd_elf_parse_eh_frame_entry (info, sec, &cookie);
fini_reloc_cookie_rels (&cookie, sec);
@@ -14448,7 +14458,8 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
if (sec == NULL || sec->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
continue;
sec = bfd_get_section_by_name (sub, ".eh_frame");
- while (sec && init_reloc_cookie_for_section (&cookie, info, sec))
+ while (sec && init_reloc_cookie_for_section (&cookie, info, sec,
+ false))
{
_bfd_elf_parse_eh_frame (sub, info, sec, &cookie);
if (elf_section_data (sec)->sec_info
@@ -14960,7 +14971,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
continue;
- if (!init_reloc_cookie_for_section (&cookie, info, i))
+ if (!init_reloc_cookie_for_section (&cookie, info, i, false))
return -1;
if (_bfd_discard_section_stabs (abfd, i,
@@ -14991,7 +15002,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
continue;
- if (!init_reloc_cookie_for_section (&cookie, info, i))
+ if (!init_reloc_cookie_for_section (&cookie, info, i, false))
return -1;
_bfd_elf_parse_eh_frame (abfd, info, i, &cookie);
@@ -15056,7 +15067,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
continue;
- if (!init_reloc_cookie_for_section (&cookie, info, i))
+ if (!init_reloc_cookie_for_section (&cookie, info, i, false))
return -1;
if (_bfd_elf_parse_sframe (abfd, info, i, &cookie))
@@ -15092,7 +15103,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
if (bed->elf_backend_discard_info != NULL)
{
- if (!init_reloc_cookie (&cookie, info, abfd))
+ if (!init_reloc_cookie (&cookie, info, abfd, false))
return -1;
if ((*bed->elf_backend_discard_info) (abfd, &cookie, info))