Merge from vendor branch OPENSSH:
[dragonfly.git] / contrib / binutils-2.14 / bfd / merge.c
1 /* SEC_MERGE support.
2    Copyright 2001, 2002 Free Software Foundation, Inc.
3    Written by Jakub Jelinek <jakub@redhat.com>.
4
5    This file is part of BFD, the Binary File Descriptor library.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 /* This file contains support for merging duplicate entities within sections,
22    as used in ELF SHF_MERGE.  */
23
24 #include "bfd.h"
25 #include "sysdep.h"
26 #include "libbfd.h"
27 #include "hashtab.h"
28 #include "libiberty.h"
29
30 struct sec_merge_sec_info;
31
32 /* An entry in the section merge hash table.  */
33
34 struct sec_merge_hash_entry
35 {
36   struct bfd_hash_entry root;
37   /* Length of this entry.  */
38   unsigned int len;
39   /* Start of this string needs to be aligned to
40      alignment octets (not 1 << align).  */
41   unsigned int alignment;
42   union
43   {
44     /* Index within the merged section.  */
45     bfd_size_type index;
46     /* Entity size (if present in suffix hash tables).  */
47     unsigned int entsize;
48     /* Entry this is a suffix of (if alignment is 0).  */
49     struct sec_merge_hash_entry *suffix;
50   } u;
51   /* Which section is it in.  */
52   struct sec_merge_sec_info *secinfo;
53   /* Next entity in the hash table.  */
54   struct sec_merge_hash_entry *next;
55 };
56
57 /* The section merge hash table.  */
58
59 struct sec_merge_hash
60 {
61   struct bfd_hash_table table;
62   /* Next available index.  */
63   bfd_size_type size;
64   /* First entity in the SEC_MERGE sections of this type.  */
65   struct sec_merge_hash_entry *first;
66   /* Last entity in the SEC_MERGE sections of this type.  */
67   struct sec_merge_hash_entry *last;
68   /* Entity size.  */
69   unsigned int entsize;
70   /* Are entries fixed size or zero terminated strings?  */
71   bfd_boolean strings;
72 };
73
74 struct sec_merge_info
75 {
76   /* Chain of sec_merge_infos.  */
77   struct sec_merge_info *next;
78   /* Chain of sec_merge_sec_infos.  */
79   struct sec_merge_sec_info *chain;
80   /* A hash table used to hold section content.  */
81   struct sec_merge_hash *htab;
82 };
83
84 struct sec_merge_sec_info
85 {
86   /* Chain of sec_merge_sec_infos.  */
87   struct sec_merge_sec_info *next;
88   /* The corresponding section.  */
89   asection *sec;
90   /* Pointer to merge_info pointing to us.  */
91   PTR *psecinfo;
92   /* A hash table used to hold section content.  */
93   struct sec_merge_hash *htab;
94   /* First string in this section.  */
95   struct sec_merge_hash_entry *first;
96   /* Original section content.  */
97   unsigned char contents[1];
98 };
99
100 static struct bfd_hash_entry *sec_merge_hash_newfunc
101   PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
102 static struct sec_merge_hash_entry *sec_merge_hash_lookup
103   PARAMS ((struct sec_merge_hash *, const char *, unsigned int, bfd_boolean));
104 static struct sec_merge_hash *sec_merge_init
105   PARAMS ((unsigned int, bfd_boolean));
106 static struct sec_merge_hash_entry *sec_merge_add
107   PARAMS ((struct sec_merge_hash *, const char *, unsigned int,
108            struct sec_merge_sec_info *));
109 static bfd_boolean sec_merge_emit
110   PARAMS ((bfd *, struct sec_merge_hash_entry *));
111 static int cmplengthentry
112   PARAMS ((const PTR, const PTR));
113 static int last4_eq
114   PARAMS ((const PTR, const PTR));
115 static int last_eq
116   PARAMS ((const PTR, const PTR));
117 static bfd_boolean record_section
118   PARAMS ((struct sec_merge_info *, struct sec_merge_sec_info *));
119 static void merge_strings
120   PARAMS ((struct sec_merge_info *));
121
122 /* Routine to create an entry in a section merge hashtab.  */
123
124 static struct bfd_hash_entry *
125 sec_merge_hash_newfunc (entry, table, string)
126      struct bfd_hash_entry *entry;
127      struct bfd_hash_table *table;
128      const char *string;
129 {
130   struct sec_merge_hash_entry *ret = (struct sec_merge_hash_entry *) entry;
131
132   /* Allocate the structure if it has not already been allocated by a
133      subclass.  */
134   if (ret == (struct sec_merge_hash_entry *) NULL)
135     ret = ((struct sec_merge_hash_entry *)
136            bfd_hash_allocate (table, sizeof (struct sec_merge_hash_entry)));
137   if (ret == (struct sec_merge_hash_entry *) NULL)
138     return NULL;
139
140   /* Call the allocation method of the superclass.  */
141   ret = ((struct sec_merge_hash_entry *)
142          bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
143
144   if (ret)
145     {
146       /* Initialize the local fields.  */
147       ret->u.suffix = NULL;
148       ret->alignment = 0;
149       ret->secinfo = NULL;
150       ret->next = NULL;
151     }
152
153   return (struct bfd_hash_entry *) ret;
154 }
155
156 /* Look up an entry in a section merge hash table.  */
157
158 static struct sec_merge_hash_entry *
159 sec_merge_hash_lookup (table, string, alignment, create)
160      struct sec_merge_hash *table;
161      const char *string;
162      unsigned int alignment;
163      bfd_boolean create;
164 {
165   register const unsigned char *s;
166   register unsigned long hash;
167   register unsigned int c;
168   struct sec_merge_hash_entry *hashp;
169   unsigned int len, i;
170   unsigned int index;
171
172   hash = 0;
173   len = 0;
174   s = (const unsigned char *) string;
175   if (table->strings)
176     {
177       if (table->entsize == 1)
178         {
179           while ((c = *s++) != '\0')
180             {
181               hash += c + (c << 17);
182               hash ^= hash >> 2;
183               ++len;
184             }
185           hash += len + (len << 17);
186         }
187       else
188         {
189           for (;;)
190             {
191               for (i = 0; i < table->entsize; ++i)
192                 if (s[i] != '\0')
193                   break;
194               if (i == table->entsize)
195                 break;
196               for (i = 0; i < table->entsize; ++i)
197                 {
198                   c = *s++;
199                   hash += c + (c << 17);
200                   hash ^= hash >> 2;
201                 }
202               ++len;
203             }
204           hash += len + (len << 17);
205           len *= table->entsize;
206         }
207       hash ^= hash >> 2;
208       len += table->entsize;
209     }
210   else
211     {
212       for (i = 0; i < table->entsize; ++i)
213         {
214           c = *s++;
215           hash += c + (c << 17);
216           hash ^= hash >> 2;
217         }
218       len = table->entsize;
219     }
220
221   index = hash % table->table.size;
222   for (hashp = (struct sec_merge_hash_entry *) table->table.table[index];
223        hashp != (struct sec_merge_hash_entry *) NULL;
224        hashp = (struct sec_merge_hash_entry *) hashp->root.next)
225     {
226       if (hashp->root.hash == hash
227           && len == hashp->len
228           && memcmp (hashp->root.string, string, len) == 0)
229         {
230           /* If the string we found does not have at least the required
231              alignment, we need to insert another copy.  */
232           if (hashp->alignment < alignment)
233             {
234               /*  Mark the less aligned copy as deleted.  */
235               hashp->len = 0;
236               hashp->alignment = 0;
237               break;
238             }
239           return hashp;
240         }
241     }
242
243   if (! create)
244     return (struct sec_merge_hash_entry *) NULL;
245
246   hashp = (struct sec_merge_hash_entry *)
247           sec_merge_hash_newfunc ((struct bfd_hash_entry *) NULL,
248                                   (struct bfd_hash_table *) table, string);
249   if (hashp == (struct sec_merge_hash_entry *) NULL)
250     return (struct sec_merge_hash_entry *) NULL;
251   hashp->root.string = string;
252   hashp->root.hash = hash;
253   hashp->len = len;
254   hashp->alignment = alignment;
255   hashp->root.next = table->table.table[index];
256   table->table.table[index] = (struct bfd_hash_entry *) hashp;
257
258   return hashp;
259 }
260
261 /* Create a new hash table.  */
262
263 static struct sec_merge_hash *
264 sec_merge_init (entsize, strings)
265      unsigned int entsize;
266      bfd_boolean strings;
267 {
268   struct sec_merge_hash *table;
269   bfd_size_type amt = sizeof (struct sec_merge_hash);
270
271   table = (struct sec_merge_hash *) bfd_malloc (amt);
272   if (table == NULL)
273     return NULL;
274
275   if (! bfd_hash_table_init (&table->table, sec_merge_hash_newfunc))
276     {
277       free (table);
278       return NULL;
279     }
280
281   table->size = 0;
282   table->first = NULL;
283   table->last = NULL;
284   table->entsize = entsize;
285   table->strings = strings;
286
287   return table;
288 }
289
290 /* Get the index of an entity in a hash table, adding it if it is not
291    already present.  */
292
293 static struct sec_merge_hash_entry *
294 sec_merge_add (tab, str, alignment, secinfo)
295      struct sec_merge_hash *tab;
296      const char *str;
297      unsigned int alignment;
298      struct sec_merge_sec_info *secinfo;
299 {
300   register struct sec_merge_hash_entry *entry;
301
302   entry = sec_merge_hash_lookup (tab, str, alignment, TRUE);
303   if (entry == NULL)
304     return NULL;
305
306   if (entry->secinfo == NULL)
307     {
308       tab->size++;
309       entry->secinfo = secinfo;
310       if (tab->first == NULL)
311         tab->first = entry;
312       else
313         tab->last->next = entry;
314       tab->last = entry;
315     }
316
317   return entry;
318 }
319
320 static bfd_boolean
321 sec_merge_emit (abfd, entry)
322      register bfd *abfd;
323      struct sec_merge_hash_entry *entry;
324 {
325   struct sec_merge_sec_info *secinfo = entry->secinfo;
326   asection *sec = secinfo->sec;
327   char *pad = "";
328   bfd_size_type off = 0;
329   int alignment_power = bfd_get_section_alignment (abfd, sec->output_section);
330
331   if (alignment_power)
332     pad = bfd_zmalloc ((bfd_size_type) 1 << alignment_power);
333
334   for (; entry != NULL && entry->secinfo == secinfo; entry = entry->next)
335     {
336       register const char *str;
337       register size_t len;
338
339       len = off & (entry->alignment - 1);
340       if (len)
341         {
342           len = entry->alignment - len;
343           if (bfd_bwrite ((PTR) pad, (bfd_size_type) len, abfd) != len)
344             break;
345           off += len;
346         }
347
348       str = entry->root.string;
349       len = entry->len;
350
351       if (bfd_bwrite ((PTR) str, (bfd_size_type) len, abfd) != len)
352         break;
353
354       off += len;
355     }
356
357   if (alignment_power)
358     free (pad);
359
360   return entry == NULL || entry->secinfo != secinfo;
361 }
362
363 /* This function is called for each input file from the add_symbols
364    pass of the linker.  */
365
366 bfd_boolean
367 _bfd_merge_section (abfd, psinfo, sec, psecinfo)
368      bfd *abfd;
369      PTR *psinfo;
370      asection *sec;
371      PTR *psecinfo;
372 {
373   struct sec_merge_info *sinfo;
374   struct sec_merge_sec_info *secinfo;
375   unsigned int align;
376   bfd_size_type amt;
377
378   if (sec->_raw_size == 0
379       || (sec->flags & SEC_EXCLUDE)
380       || (sec->flags & SEC_MERGE) == 0
381       || sec->entsize == 0)
382     return TRUE;
383
384   if ((sec->flags & SEC_RELOC) != 0)
385     {
386       /* We aren't prepared to handle relocations in merged sections.  */
387       return TRUE;
388     }
389
390   align = bfd_get_section_alignment (sec->owner, sec);
391   if ((sec->entsize < (unsigned int)(1 << align)
392        && ((sec->entsize & (sec->entsize - 1))
393            || !(sec->flags & SEC_STRINGS)))
394       || (sec->entsize > (unsigned int)(1 << align)
395           && (sec->entsize & ((1 << align) - 1))))
396     {
397       /* Sanity check.  If string character size is smaller than
398          alignment, then we require character size to be a power
399          of 2, otherwise character size must be integer multiple
400          of alignment.  For non-string constants, alignment must
401          be smaller than or equal to entity size and entity size
402          must be integer multiple of alignment.  */
403       return TRUE;
404     }
405
406   for (sinfo = (struct sec_merge_info *) *psinfo; sinfo; sinfo = sinfo->next)
407     if ((secinfo = sinfo->chain)
408         && ! ((secinfo->sec->flags ^ sec->flags) & (SEC_MERGE | SEC_STRINGS))
409         && secinfo->sec->entsize == sec->entsize
410         && ! strcmp (secinfo->sec->name, sec->name))
411       break;
412
413   if (sinfo == NULL)
414     {
415       /* Initialize the information we need to keep track of.  */
416       amt = sizeof (struct sec_merge_info);
417       sinfo = (struct sec_merge_info *) bfd_alloc (abfd, amt);
418       if (sinfo == NULL)
419         goto error_return;
420       sinfo->next = (struct sec_merge_info *) *psinfo;
421       sinfo->chain = NULL;
422       *psinfo = (PTR) sinfo;
423       sinfo->htab = sec_merge_init (sec->entsize, (sec->flags & SEC_STRINGS));
424       if (sinfo->htab == NULL)
425         goto error_return;
426     }
427
428   /* Read the section from abfd.  */
429
430   amt = sizeof (struct sec_merge_sec_info) + sec->_raw_size - 1;
431   *psecinfo = bfd_alloc (abfd, amt);
432   if (*psecinfo == NULL)
433     goto error_return;
434
435   secinfo = (struct sec_merge_sec_info *)*psecinfo;
436   if (sinfo->chain)
437     {
438       secinfo->next = sinfo->chain->next;
439       sinfo->chain->next = secinfo;
440     }
441   else
442     secinfo->next = secinfo;
443   sinfo->chain = secinfo;
444   secinfo->sec = sec;
445   secinfo->psecinfo = psecinfo;
446   secinfo->htab = sinfo->htab;
447   secinfo->first = NULL;
448
449   if (! bfd_get_section_contents (sec->owner, sec, secinfo->contents,
450                                   (bfd_vma) 0, sec->_raw_size))
451     goto error_return;
452
453   return TRUE;
454
455  error_return:
456   *psecinfo = NULL;
457   return FALSE;
458 }
459
460 /* Compare two sec_merge_hash_entry structures.  This is called via qsort.  */
461
462 static int
463 cmplengthentry (a, b)
464      const PTR a;
465      const PTR b;
466 {
467   struct sec_merge_hash_entry * A = *(struct sec_merge_hash_entry **) a;
468   struct sec_merge_hash_entry * B = *(struct sec_merge_hash_entry **) b;
469
470   if (A->len < B->len)
471     return 1;
472   else if (A->len > B->len)
473     return -1;
474
475   return memcmp (A->root.string, B->root.string, A->len);
476 }
477
478 static int
479 last4_eq (a, b)
480      const PTR a;
481      const PTR b;
482 {
483   struct sec_merge_hash_entry * A = (struct sec_merge_hash_entry *) a;
484   struct sec_merge_hash_entry * B = (struct sec_merge_hash_entry *) b;
485
486   if (memcmp (A->root.string + A->len - 5 * A->u.entsize,
487               B->root.string + B->len - 5 * A->u.entsize,
488               4 * A->u.entsize) != 0)
489     /* This was a hashtable collision.  */
490     return 0;
491
492   if (A->len <= B->len)
493     /* B cannot be a suffix of A unless A is equal to B, which is guaranteed
494        not to be equal by the hash table.  */
495     return 0;
496
497   if (A->alignment < B->alignment
498       || ((A->len - B->len) & (B->alignment - 1)))
499     /* The suffix is not sufficiently aligned.  */
500     return 0;
501
502   return memcmp (A->root.string + (A->len - B->len),
503                  B->root.string, B->len - 5 * A->u.entsize) == 0;
504 }
505
506 static int
507 last_eq (a, b)
508      const PTR a;
509      const PTR b;
510 {
511   struct sec_merge_hash_entry * A = (struct sec_merge_hash_entry *) a;
512   struct sec_merge_hash_entry * B = (struct sec_merge_hash_entry *) b;
513
514   if (B->len >= 5 * A->u.entsize)
515     /* Longer strings are just pushed into the hash table,
516        they'll be used when looking up for very short strings.  */
517     return 0;
518
519   if (memcmp (A->root.string + A->len - 2 * A->u.entsize,
520               B->root.string + B->len - 2 * A->u.entsize,
521               A->u.entsize) != 0)
522     /* This was a hashtable collision.  */
523     return 0;
524
525   if (A->len <= B->len)
526     /* B cannot be a suffix of A unless A is equal to B, which is guaranteed
527        not to be equal by the hash table.  */
528     return 0;
529
530   if (A->alignment < B->alignment
531       || ((A->len - B->len) & (B->alignment - 1)))
532     /* The suffix is not sufficiently aligned.  */
533     return 0;
534
535   return memcmp (A->root.string + (A->len - B->len),
536                  B->root.string, B->len - 2 * A->u.entsize) == 0;
537 }
538
539 /* Record one section into the hash table.  */
540 static bfd_boolean
541 record_section (sinfo, secinfo)
542      struct sec_merge_info *sinfo;
543      struct sec_merge_sec_info *secinfo;
544 {
545   asection *sec = secinfo->sec;
546   struct sec_merge_hash_entry *entry;
547   bfd_boolean nul;
548   unsigned char *p, *end;
549   bfd_vma mask, eltalign;
550   unsigned int align, i;
551
552   align = bfd_get_section_alignment (sec->owner, sec);
553   end = secinfo->contents + sec->_raw_size;
554   nul = FALSE;
555   mask = ((bfd_vma) 1 << align) - 1;
556   if (sec->flags & SEC_STRINGS)
557     {
558       for (p = secinfo->contents; p < end; )
559         {
560           eltalign = p - secinfo->contents;
561           eltalign = ((eltalign ^ (eltalign - 1)) + 1) >> 1;
562           if (!eltalign || eltalign > mask)
563             eltalign = mask + 1;
564           entry = sec_merge_add (sinfo->htab, p, (unsigned) eltalign, secinfo);
565           if (! entry)
566             goto error_return;
567           p += entry->len;
568           if (sec->entsize == 1)
569             {
570               while (p < end && *p == 0)
571                 {
572                   if (!nul && !((p - secinfo->contents) & mask))
573                     {
574                       nul = TRUE;
575                       entry = sec_merge_add (sinfo->htab, "",
576                                              (unsigned) mask + 1, secinfo);
577                       if (! entry)
578                         goto error_return;
579                     }
580                   p++;
581                 }
582             }
583           else
584             {
585               while (p < end)
586                 {
587                   for (i = 0; i < sec->entsize; i++)
588                     if (p[i] != '\0')
589                       break;
590                   if (i != sec->entsize)
591                     break;
592                   if (!nul && !((p - secinfo->contents) & mask))
593                     {
594                       nul = TRUE;
595                       entry = sec_merge_add (sinfo->htab, p,
596                                              (unsigned) mask + 1, secinfo);
597                       if (! entry)
598                         goto error_return;
599                     }
600                   p += sec->entsize;
601                 }
602             }
603         }
604     }
605   else
606     {
607       for (p = secinfo->contents; p < end; p += sec->entsize)
608         {
609           entry = sec_merge_add (sinfo->htab, p, 1, secinfo);
610           if (! entry)
611             goto error_return;
612         }
613     }
614
615   return TRUE;
616
617 error_return:
618   for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
619     *secinfo->psecinfo = NULL;
620   return FALSE;
621 }
622
623 /* This is a helper function for _bfd_merge_sections.  It attempts to
624    merge strings matching suffixes of longer strings.  */
625 static void
626 merge_strings (sinfo)
627      struct sec_merge_info *sinfo;
628 {
629   struct sec_merge_hash_entry **array, **a, **end, *e;
630   struct sec_merge_sec_info *secinfo;
631   htab_t lasttab = NULL, last4tab = NULL;
632   bfd_size_type size, amt;
633
634   /* Now sort the strings by length, longest first.  */
635   array = NULL;
636   amt = sinfo->htab->size * sizeof (struct sec_merge_hash_entry *);
637   array = (struct sec_merge_hash_entry **) bfd_malloc (amt);
638   if (array == NULL)
639     goto alloc_failure;
640
641   for (e = sinfo->htab->first, a = array; e; e = e->next)
642     if (e->alignment)
643       *a++ = e;
644
645   sinfo->htab->size = a - array;
646
647   qsort (array, (size_t) sinfo->htab->size,
648          sizeof (struct sec_merge_hash_entry *), cmplengthentry);
649
650   last4tab = htab_create_alloc ((size_t) sinfo->htab->size * 4,
651                                 NULL, last4_eq, NULL, calloc, free);
652   lasttab = htab_create_alloc ((size_t) sinfo->htab->size * 4,
653                                NULL, last_eq, NULL, calloc, free);
654   if (lasttab == NULL || last4tab == NULL)
655     goto alloc_failure;
656
657   /* Now insert the strings into hash tables (strings with last 4 characters
658      and strings with last character equal), look for longer strings which
659      we're suffix of.  */
660   for (a = array, end = array + sinfo->htab->size; a < end; a++)
661     {
662       register hashval_t hash;
663       unsigned int c;
664       unsigned int i;
665       const unsigned char *s;
666       PTR *p;
667
668       e = *a;
669       e->u.entsize = sinfo->htab->entsize;
670       if (e->len <= e->u.entsize)
671         break;
672       if (e->len > 4 * e->u.entsize)
673         {
674           s = (const unsigned char *) (e->root.string + e->len - e->u.entsize);
675           hash = 0;
676           for (i = 0; i < 4 * e->u.entsize; i++)
677             {
678               c = *--s;
679               hash += c + (c << 17);
680               hash ^= hash >> 2;
681             }
682           p = htab_find_slot_with_hash (last4tab, e, hash, INSERT);
683           if (p == NULL)
684             goto alloc_failure;
685           if (*p)
686             {
687               struct sec_merge_hash_entry *ent;
688
689               ent = (struct sec_merge_hash_entry *) *p;
690               e->u.suffix = ent;
691               e->alignment = 0;
692               continue;
693             }
694           else
695             *p = (PTR) e;
696         }
697       s = (const unsigned char *) (e->root.string + e->len - e->u.entsize);
698       hash = 0;
699       for (i = 0; i < e->u.entsize; i++)
700         {
701           c = *--s;
702           hash += c + (c << 17);
703           hash ^= hash >> 2;
704         }
705       p = htab_find_slot_with_hash (lasttab, e, hash, INSERT);
706       if (p == NULL)
707         goto alloc_failure;
708       if (*p)
709         {
710           struct sec_merge_hash_entry *ent;
711
712           ent = (struct sec_merge_hash_entry *) *p;
713           e->u.suffix = ent;
714           e->alignment = 0;
715         }
716       else
717         *p = (PTR) e;
718     }
719
720 alloc_failure:
721   if (array)
722     free (array);
723   if (lasttab)
724     htab_delete (lasttab);
725   if (last4tab)
726     htab_delete (last4tab);
727
728   /* Now assign positions to the strings we want to keep.  */
729   size = 0;
730   secinfo = sinfo->htab->first->secinfo;
731   for (e = sinfo->htab->first; e; e = e->next)
732     {
733       if (e->secinfo != secinfo)
734         {
735           secinfo->sec->_cooked_size = size;
736           secinfo = e->secinfo;
737         }
738       if (e->alignment)
739         {
740           if (e->secinfo->first == NULL)
741             {
742               e->secinfo->first = e;
743               size = 0;
744             }
745           size = (size + e->alignment - 1) & ~((bfd_vma) e->alignment - 1);
746           e->u.index = size;
747           size += e->len;
748         }
749     }
750   secinfo->sec->_cooked_size = size;
751
752   /* And now adjust the rest, removing them from the chain (but not hashtable)
753      at the same time.  */
754   for (a = &sinfo->htab->first, e = *a; e; e = e->next)
755     if (e->alignment)
756       a = &e->next;
757     else
758       {
759         *a = e->next;
760         if (e->len)
761           {
762             e->secinfo = e->u.suffix->secinfo;
763             e->alignment = e->u.suffix->alignment;
764             e->u.index = e->u.suffix->u.index + (e->u.suffix->len - e->len);
765           }
766       }
767 }
768
769 /* This function is called once after all SEC_MERGE sections are registered
770    with _bfd_merge_section.  */
771
772 bfd_boolean
773 _bfd_merge_sections (abfd, xsinfo, remove_hook)
774      bfd *abfd ATTRIBUTE_UNUSED;
775      PTR xsinfo;
776      void (*remove_hook) PARAMS((bfd *, asection *));
777 {
778   struct sec_merge_info *sinfo;
779
780   for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next)
781     {
782       struct sec_merge_sec_info * secinfo;
783
784       if (! sinfo->chain)
785         continue;
786
787       /* Move sinfo->chain to head of the chain, terminate it.  */
788       secinfo = sinfo->chain;
789       sinfo->chain = secinfo->next;
790       secinfo->next = NULL;
791
792       /* Record the sections into the hash table.  */
793       for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
794         if (secinfo->sec->flags & SEC_EXCLUDE)
795           {
796             *secinfo->psecinfo = NULL;
797             if (remove_hook)
798               (*remove_hook) (abfd, secinfo->sec);
799           }
800         else if (! record_section (sinfo, secinfo))
801           break;
802
803       if (secinfo)
804         continue;
805
806       if (sinfo->htab->first == NULL)
807         continue;
808
809       if (sinfo->htab->strings)
810         merge_strings (sinfo);
811       else
812         {
813           struct sec_merge_hash_entry *e;
814           bfd_size_type size = 0;
815
816           /* Things are much simpler for non-strings.
817              Just assign them slots in the section.  */
818           secinfo = NULL;
819           for (e = sinfo->htab->first; e; e = e->next)
820             {
821               if (e->secinfo->first == NULL)
822                 {
823                   if (secinfo)
824                     secinfo->sec->_cooked_size = size;
825                   e->secinfo->first = e;
826                   size = 0;
827                 }
828               size = (size + e->alignment - 1)
829                      & ~((bfd_vma) e->alignment - 1);
830               e->u.index = size;
831               size += e->len;
832               secinfo = e->secinfo;
833             }
834           secinfo->sec->_cooked_size = size;
835         }
836
837         /* Finally shrink all input sections which have not made it into
838            the hash table at all.  */
839         for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
840           if (secinfo->first == NULL)
841             secinfo->sec->_cooked_size = 0;
842     }
843
844   return TRUE;
845 }
846
847 /* Write out the merged section.  */
848
849 bfd_boolean
850 _bfd_write_merged_section (output_bfd, sec, psecinfo)
851      bfd *output_bfd;
852      asection *sec;
853      PTR psecinfo;
854 {
855   struct sec_merge_sec_info *secinfo;
856   file_ptr pos;
857
858   secinfo = (struct sec_merge_sec_info *) psecinfo;
859
860   if (!secinfo->first)
861     return TRUE;
862
863   pos = sec->output_section->filepos + sec->output_offset;
864   if (bfd_seek (output_bfd, pos, SEEK_SET) != 0)
865     return FALSE;
866
867   if (! sec_merge_emit (output_bfd, secinfo->first))
868     return FALSE;
869
870   return TRUE;
871 }
872
873 /* Adjust an address in the SEC_MERGE section.  Given OFFSET within
874    *PSEC, this returns the new offset in the adjusted SEC_MERGE
875    section and writes the new section back into *PSEC.  */
876
877 bfd_vma
878 _bfd_merged_section_offset (output_bfd, psec, psecinfo, offset, addend)
879      bfd *output_bfd ATTRIBUTE_UNUSED;
880      asection **psec;
881      PTR psecinfo;
882      bfd_vma offset, addend;
883 {
884   struct sec_merge_sec_info *secinfo;
885   struct sec_merge_hash_entry *entry;
886   unsigned char *p;
887   asection *sec = *psec;
888
889   secinfo = (struct sec_merge_sec_info *) psecinfo;
890
891   if (offset + addend >= sec->_raw_size)
892     {
893       if (offset + addend > sec->_raw_size)
894         {
895           (*_bfd_error_handler)
896             (_("%s: access beyond end of merged section (%ld + %ld)"),
897              bfd_get_filename (sec->owner), (long) offset, (long) addend);
898         }
899       return (secinfo->first ? sec->_cooked_size : 0);
900     }
901
902   if (secinfo->htab->strings)
903     {
904       if (sec->entsize == 1)
905         {
906           p = secinfo->contents + offset + addend - 1;
907           while (p >= secinfo->contents && *p)
908             --p;
909           ++p;
910         }
911       else
912         {
913           p = secinfo->contents
914               + ((offset + addend) / sec->entsize) * sec->entsize;
915           p -= sec->entsize;
916           while (p >= secinfo->contents)
917             {
918               unsigned int i;
919
920               for (i = 0; i < sec->entsize; ++i)
921                 if (p[i] != '\0')
922                   break;
923               if (i == sec->entsize)
924                 break;
925               p -= sec->entsize;
926             }
927           p += sec->entsize;
928         }
929     }
930   else
931     {
932       p = secinfo->contents
933           + ((offset + addend) / sec->entsize) * sec->entsize;
934     }
935   entry = sec_merge_hash_lookup (secinfo->htab, p, 0, FALSE);
936   if (!entry)
937     {
938       if (! secinfo->htab->strings)
939         abort ();
940       /* This should only happen if somebody points into the padding
941          after a NUL character but before next entity.  */
942       if (*p)
943         abort ();
944       if (! secinfo->htab->first)
945         abort ();
946       entry = secinfo->htab->first;
947       p = secinfo->contents
948           + ((offset + addend) / sec->entsize + 1) * sec->entsize
949           - entry->len;
950     }
951
952   *psec = entry->secinfo->sec;
953   return entry->u.index + (secinfo->contents + offset - p);
954 }