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