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