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