on_needed_list (const char *soname, struct bfd_link_needed_list *needed)
{
for (; needed != NULL; needed = needed->next)
- if (strcmp (soname, needed->name) == 0)
+ if ((elf_dyn_lib_class (needed->by) & DYN_AS_NEEDED) == 0
+ && strcmp (soname, needed->name) == 0)
return TRUE;
return FALSE;
struct bfd_link_info *info,
enum notice_asneeded_action act)
{
- return (*info->callbacks->notice) (info, NULL, ibfd, NULL, act, 0, NULL);
+ return (*info->callbacks->notice) (info, NULL, NULL, ibfd, NULL, act, 0);
}
/* Add symbols from an ELF object file to the linker hash table. */
bfd_size_type old_dynstr_size = 0;
size_t tabsize = 0;
asection *s;
+ bfd_boolean just_syms;
htab = elf_hash_table (info);
bed = get_elf_backend_data (abfd);
}
}
+ just_syms = ((s = abfd->sections) != NULL
+ && s->sec_info_type == SEC_INFO_TYPE_JUST_SYMS);
+
add_needed = TRUE;
if (! dynamic)
{
/* If we are creating a shared library, create all the dynamic
sections immediately. We need to attach them to something,
so we attach them to this BFD, provided it is the right
- format. FIXME: If there are no input BFD's of the same
- format as the output, we can't make a shared library. */
- if (info->shared
+ format and is not from ld --just-symbols. FIXME: If there
+ are no input BFD's of the same format as the output, we can't
+ make a shared library. */
+ if (!just_syms
+ && info->shared
&& is_elf_hash_table (htab)
&& info->output_bfd->xvec == abfd->xvec
&& !htab->dynamic_sections_created)
/* ld --just-symbols and dynamic objects don't mix very well.
ld shouldn't allow it. */
- if ((s = abfd->sections) != NULL
- && s->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
+ if (just_syms)
abort ();
/* If this dynamic lib was specified on the command line with
esdo->rela.count = 0;
}
- _bfd_elf_assign_file_positions_for_relocs (abfd);
-
/* We have now assigned file positions for all the sections except
- .symtab and .strtab. We start the .symtab section at the current
- file position, and write directly to it. We build the .strtab
- section in memory. */
+ .symtab, .strtab, and non-loaded reloc sections. We start the
+ .symtab section at the current file position, and write directly
+ to it. We build the .strtab section in memory. */
bfd_get_symcount (abfd) = 0;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
/* sh_name is set in prep_headers. */
bfd *sub;
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;
if (!bed->can_gc_sections
|| !is_elf_hash_table (info->hash))
}
bed->gc_keep (info);
+ htab = elf_hash_table (info);
/* Try to parse each bfd's .eh_frame section. Point elf_eh_frame_section
at the .eh_frame section if we can mark the FDEs individually. */
- _bfd_elf_begin_eh_frame_parsing (info);
for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
{
asection *sec;
sec = bfd_get_next_section_by_name (sec);
}
}
- _bfd_elf_end_eh_frame_parsing (info);
/* Apply transitive closure to the vtable entry usage info. */
- elf_link_hash_traverse (elf_hash_table (info),
- elf_gc_propagate_vtable_entries_used,
- &ok);
+ elf_link_hash_traverse (htab, elf_gc_propagate_vtable_entries_used, &ok);
if (!ok)
return FALSE;
/* Kill the vtable relocations that were not used. */
- elf_link_hash_traverse (elf_hash_table (info),
- elf_gc_smash_unused_vtentry_relocs,
- &ok);
+ elf_link_hash_traverse (htab, elf_gc_smash_unused_vtentry_relocs, &ok);
if (!ok)
return FALSE;
/* Mark dynamically referenced symbols. */
- if (elf_hash_table (info)->dynamic_sections_created)
- elf_link_hash_traverse (elf_hash_table (info),
- bed->gc_mark_dynamic_ref,
- info);
+ if (htab->dynamic_sections_created)
+ elf_link_hash_traverse (htab, bed->gc_mark_dynamic_ref, info);
/* Grovel through relocs to find out who stays ... */
gc_mark_hook = bed->gc_mark_hook;
if ((h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
- && discarded_section (h->root.u.def.section))
+ && (h->root.u.def.section->owner != rcookie->abfd
+ || h->root.u.def.section->kept_section != NULL
+ || discarded_section (h->root.u.def.section)))
return TRUE;
- else
- return FALSE;
}
else
{
/* Need to: get the symbol; get the section. */
isym = &rcookie->locsyms[r_symndx];
isec = bfd_section_from_elf_index (rcookie->abfd, isym->st_shndx);
- if (isec != NULL && discarded_section (isec))
+ if (isec != NULL
+ && (isec->kept_section != NULL
+ || discarded_section (isec)))
return TRUE;
}
return FALSE;
}
/* Discard unneeded references to discarded sections.
- Returns TRUE if any section's size was changed. */
-/* This function assumes that the relocations are in sorted order,
- which is true for all known assemblers. */
+ Returns -1 on error, 1 if any section's size was changed, 0 if
+ nothing changed. This function assumes that the relocations are in
+ sorted order, which is true for all known assemblers. */
-bfd_boolean
+int
bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
{
struct elf_reloc_cookie cookie;
- asection *stab, *eh;
- const struct elf_backend_data *bed;
+ asection *o;
bfd *abfd;
- bfd_boolean ret = FALSE;
+ int changed = 0;
if (info->traditional_format
|| !is_elf_hash_table (info->hash))
- return FALSE;
+ return 0;
- _bfd_elf_begin_eh_frame_parsing (info);
- for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next)
+ o = bfd_get_section_by_name (output_bfd, ".stab");
+ if (o != NULL)
{
- if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
- continue;
+ asection *i;
- bed = get_elf_backend_data (abfd);
-
- eh = NULL;
- if (!info->relocatable)
+ for (i = o->map_head.s; i != NULL; i = i->map_head.s)
{
- eh = bfd_get_section_by_name (abfd, ".eh_frame");
- while (eh != NULL
- && (eh->size == 0
- || bfd_is_abs_section (eh->output_section)))
- eh = bfd_get_next_section_by_name (eh);
- }
-
- stab = bfd_get_section_by_name (abfd, ".stab");
- if (stab != NULL
- && (stab->size == 0
- || bfd_is_abs_section (stab->output_section)
- || stab->sec_info_type != SEC_INFO_TYPE_STABS))
- stab = NULL;
+ if (i->size == 0
+ || i->reloc_count == 0
+ || i->sec_info_type != SEC_INFO_TYPE_STABS)
+ continue;
- if (stab == NULL
- && eh == NULL
- && bed->elf_backend_discard_info == NULL)
- continue;
+ abfd = i->owner;
+ if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
+ continue;
- if (!init_reloc_cookie (&cookie, info, abfd))
- return FALSE;
+ if (!init_reloc_cookie_for_section (&cookie, info, i))
+ return -1;
- if (stab != NULL
- && stab->reloc_count > 0
- && init_reloc_cookie_rels (&cookie, info, abfd, stab))
- {
- if (_bfd_discard_section_stabs (abfd, stab,
- elf_section_data (stab)->sec_info,
+ if (_bfd_discard_section_stabs (abfd, i,
+ elf_section_data (i)->sec_info,
bfd_elf_reloc_symbol_deleted_p,
&cookie))
- ret = TRUE;
- fini_reloc_cookie_rels (&cookie, stab);
+ changed = 1;
+
+ fini_reloc_cookie_for_section (&cookie, i);
}
+ }
- while (eh != NULL
- && init_reloc_cookie_rels (&cookie, info, abfd, eh))
+ o = bfd_get_section_by_name (output_bfd, ".eh_frame");
+ if (o != NULL)
+ {
+ asection *i;
+
+ for (i = o->map_head.s; i != NULL; i = i->map_head.s)
{
- _bfd_elf_parse_eh_frame (abfd, info, eh, &cookie);
- if (_bfd_elf_discard_section_eh_frame (abfd, info, eh,
+ if (i->size == 0)
+ continue;
+
+ abfd = i->owner;
+ if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
+ continue;
+
+ if (!init_reloc_cookie_for_section (&cookie, info, i))
+ return -1;
+
+ _bfd_elf_parse_eh_frame (abfd, info, i, &cookie);
+ if (_bfd_elf_discard_section_eh_frame (abfd, info, i,
bfd_elf_reloc_symbol_deleted_p,
&cookie))
- ret = TRUE;
- fini_reloc_cookie_rels (&cookie, eh);
- eh = bfd_get_next_section_by_name (eh);
+ changed = 1;
+
+ fini_reloc_cookie_for_section (&cookie, i);
}
+ }
- if (bed->elf_backend_discard_info != NULL
- && (*bed->elf_backend_discard_info) (abfd, &cookie, info))
- ret = TRUE;
+ for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next)
+ {
+ const struct elf_backend_data *bed;
- fini_reloc_cookie (&cookie, abfd);
+ if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
+ continue;
+
+ bed = get_elf_backend_data (abfd);
+
+ if (bed->elf_backend_discard_info != NULL)
+ {
+ if (!init_reloc_cookie (&cookie, info, abfd))
+ return -1;
+
+ if ((*bed->elf_backend_discard_info) (abfd, &cookie, info))
+ changed = 1;
+
+ fini_reloc_cookie (&cookie, abfd);
+ }
}
- _bfd_elf_end_eh_frame_parsing (info);
if (info->eh_frame_hdr
&& !info->relocatable
&& _bfd_elf_discard_section_eh_frame_hdr (output_bfd, info))
- ret = TRUE;
+ changed = 1;
- return ret;
+ return changed;
}
bfd_boolean