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