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