+ /* Now assign positions to the strings we want to keep. */
+ size = 0;
+ secinfo = sinfo->htab->first->secinfo;
+ for (e = sinfo->htab->first; e; e = e->next)
+ {
+ if (e->secinfo != secinfo)
+ {
+ secinfo->sec->size = size;
+ secinfo = e->secinfo;
+ }
+ if (e->alignment)
+ {
+ if (e->secinfo->first_str == NULL)
+ {
+ e->secinfo->first_str = e;
+ size = 0;
+ }
+ size = (size + e->alignment - 1) & ~((bfd_vma) e->alignment - 1);
+ e->u.index = size;
+ size += e->len;
+ }
+ }
+ secinfo->sec->size = size;
+
+ /* And now adjust the rest, removing them from the chain (but not hashtable)
+ at the same time. */
+ for (a = &sinfo->htab->first, e = *a; e; e = e->next)
+ if (e->alignment)
+ a = &e->next;
+ else
+ {
+ *a = e->next;
+ if (e->len)
+ {
+ e->secinfo = e->u.suffix->secinfo;
+ e->alignment = e->u.suffix->alignment;
+ e->u.index = e->u.suffix->u.index + (e->u.suffix->len - e->len);
+ }
+ }
+ return secinfo;
+}
+
+/* This function is called once after all SEC_MERGE sections are registered
+ with _bfd_merge_section. */
+
+bfd_boolean
+_bfd_merge_sections (bfd *abfd,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ void *xsinfo,
+ void (*remove_hook) (bfd *, asection *))
+{
+ struct sec_merge_info *sinfo;
+
+ for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next)
+ {
+ struct sec_merge_sec_info *secinfo;
+ bfd_size_type align;
+
+ if (! sinfo->chain)
+ continue;
+
+ /* Move sinfo->chain to head of the chain, terminate it. */
+ secinfo = sinfo->chain;
+ sinfo->chain = secinfo->next;
+ secinfo->next = NULL;
+
+ /* Record the sections into the hash table. */
+ align = 1;
+ for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
+ if (secinfo->sec->flags & SEC_EXCLUDE)
+ {
+ *secinfo->psecinfo = NULL;
+ if (remove_hook)
+ (*remove_hook) (abfd, secinfo->sec);
+ }
+ else
+ {
+ if (!record_section (sinfo, secinfo))
+ return FALSE;
+ if (align)
+ {
+ align = (bfd_size_type) 1 << secinfo->sec->alignment_power;
+ if ((secinfo->sec->size & (align - 1)) != 0)
+ align = 0;
+ }
+ }
+
+ if (sinfo->htab->first == NULL)
+ continue;
+
+ if (sinfo->htab->strings)
+ {
+ secinfo = merge_strings (sinfo);
+ if (!secinfo)
+ return FALSE;
+ }
+ else
+ {
+ struct sec_merge_hash_entry *e;
+ bfd_size_type size = 0;
+
+ /* Things are much simpler for non-strings.
+ Just assign them slots in the section. */
+ secinfo = NULL;
+ for (e = sinfo->htab->first; e; e = e->next)
+ {
+ if (e->secinfo->first_str == NULL)
+ {
+ if (secinfo)
+ secinfo->sec->size = size;
+ e->secinfo->first_str = e;
+ size = 0;
+ }
+ size = (size + e->alignment - 1) & ~((bfd_vma) e->alignment - 1);
+ e->u.index = size;
+ size += e->len;
+ secinfo = e->secinfo;
+ }
+ secinfo->sec->size = size;
+ }
+
+ /* If the input sections were padded according to their alignments,
+ then pad the output too. */
+ if (align)
+ secinfo->sec->size = (secinfo->sec->size + align - 1) & -align;
+
+ /* Finally remove all input sections which have not made it into
+ the hash table at all. */
+ for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
+ if (secinfo->first_str == NULL)
+ secinfo->sec->flags |= SEC_EXCLUDE | SEC_KEEP;
+ }
+
+ return TRUE;