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