+
+/*
+FUNCTION
+ bfd_copy_private_section_data
+
+SYNOPSIS
+ boolean bfd_copy_private_section_data (bfd *ibfd, asection *isec,
+ bfd *obfd, asection *osec);
+
+DESCRIPTION
+ Copy private section information from @var{isec} in the BFD
+ @var{ibfd} to the section @var{osec} in the BFD @var{obfd}.
+ Return <<true>> on success, <<false>> on error. Possible error
+ returns are:
+
+ o <<bfd_error_no_memory>> -
+ Not enough memory exists to create private data for @var{osec}.
+
+.#define bfd_copy_private_section_data(ibfd, isection, obfd, osection) \
+. BFD_SEND (obfd, _bfd_copy_private_section_data, \
+. (ibfd, isection, obfd, osection))
+*/
+
+/*
+FUNCTION
+ _bfd_strip_section_from_output
+
+SYNOPSIS
+ void _bfd_strip_section_from_output
+ (struct bfd_link_info *info, asection *section);
+
+DESCRIPTION
+ Remove @var{section} from the output. If the output section
+ becomes empty, remove it from the output bfd. @var{info} may
+ be NULL; if it is not, it is used to decide whether the output
+ section is empty.
+*/
+void
+_bfd_strip_section_from_output (info, s)
+ struct bfd_link_info *info;
+ asection *s;
+{
+ asection **spp, *os;
+ struct bfd_link_order *p, *pp;
+ boolean keep_os;
+
+ /* Excise the input section from the link order.
+
+ FIXME: For all calls that I can see to this function, the link
+ orders have not yet been set up. So why are we checking them? --
+ Ian */
+ os = s->output_section;
+
+ /* Handle a section that wasn't output. */
+ if (os == NULL)
+ return;
+
+ for (p = os->link_order_head, pp = NULL; p != NULL; pp = p, p = p->next)
+ if (p->type == bfd_indirect_link_order
+ && p->u.indirect.section == s)
+ {
+ if (pp)
+ pp->next = p->next;
+ else
+ os->link_order_head = p->next;
+ if (!p->next)
+ os->link_order_tail = pp;
+ break;
+ }
+
+ keep_os = os->link_order_head != NULL;
+
+ if (! keep_os && info != NULL)
+ {
+ bfd *abfd;
+ for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next)
+ {
+ asection *is;
+ for (is = abfd->sections; is != NULL; is = is->next)
+ {
+ if (is != s && is->output_section == os
+ && (is->flags & SEC_EXCLUDE) == 0)
+ break;
+ }
+ if (is != NULL)
+ break;
+ }
+ if (abfd != NULL)
+ keep_os = true;
+ }
+
+ /* If the output section is empty, remove it too. Careful about sections
+ that have been discarded in the link script -- they are mapped to
+ bfd_abs_section, which has no owner. */
+ if (!keep_os && os->owner != NULL)
+ {
+ for (spp = &os->owner->sections; *spp; spp = &(*spp)->next)
+ if (*spp == os)
+ {
+ bfd_section_list_remove (os->owner, spp);
+ os->owner->section_count--;
+ break;
+ }
+ }
+
+ s->flags |= SEC_EXCLUDE;
+}
+
+/*
+FUNCTION
+ bfd_discard_group
+
+SYNOPSIS
+ void bfd_discard_group (bfd *abfd, asection *group);
+
+DESCRIPTION
+ Remove all members of @var{group} from the output.
+*/
+
+void
+bfd_discard_group (abfd, group)
+ bfd *abfd;
+ asection *group;
+{
+ if ((group->flags & SEC_GROUP) != 0
+ && abfd->xvec->flavour == bfd_target_elf_flavour)
+ bfd_elf_discard_group (abfd, group);
+}