OSDN Git Service

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