Update the address and phone number of the FSF organization in the GPL notices
[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
3e110533 19 Foundation, Inc., 51 Franklin Street - Fifth Floor, 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
8423293d
AM
700_bfd_merge_sections (bfd *abfd ATTRIBUTE_UNUSED,
701 struct bfd_link_info *info ATTRIBUTE_UNUSED,
702 void *xsinfo,
703 void (*remove_hook) (bfd *, asection *))
8550eb6e
JJ
704{
705 struct sec_merge_info *sinfo;
706
707 for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next)
708 {
709 struct sec_merge_sec_info * secinfo;
710
711 if (! sinfo->chain)
712 continue;
713
714 /* Move sinfo->chain to head of the chain, terminate it. */
715 secinfo = sinfo->chain;
716 sinfo->chain = secinfo->next;
717 secinfo->next = NULL;
718
719 /* Record the sections into the hash table. */
720 for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
721 if (secinfo->sec->flags & SEC_EXCLUDE)
d3c456e9
JJ
722 {
723 *secinfo->psecinfo = NULL;
724 if (remove_hook)
725 (*remove_hook) (abfd, secinfo->sec);
726 }
8550eb6e
JJ
727 else if (! record_section (sinfo, secinfo))
728 break;
729
730 if (secinfo)
731 continue;
732
86eaf01e
JJ
733 if (sinfo->htab->first == NULL)
734 continue;
735
8550eb6e
JJ
736 if (sinfo->htab->strings)
737 merge_strings (sinfo);
738 else
739 {
740 struct sec_merge_hash_entry *e;
741 bfd_size_type size = 0;
742
743 /* Things are much simpler for non-strings.
744 Just assign them slots in the section. */
745 secinfo = NULL;
746 for (e = sinfo->htab->first; e; e = e->next)
747 {
57ceae94 748 if (e->secinfo->first_str == NULL)
8550eb6e
JJ
749 {
750 if (secinfo)
eea6121a 751 secinfo->sec->size = size;
57ceae94 752 e->secinfo->first_str = e;
8550eb6e
JJ
753 size = 0;
754 }
755 size = (size + e->alignment - 1)
756 & ~((bfd_vma) e->alignment - 1);
757 e->u.index = size;
758 size += e->len;
759 secinfo = e->secinfo;
760 }
eea6121a 761 secinfo->sec->size = size;
8550eb6e
JJ
762 }
763
27c630ba 764 /* Finally remove all input sections which have not made it into
8550eb6e
JJ
765 the hash table at all. */
766 for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
57ceae94 767 if (secinfo->first_str == NULL)
8423293d 768 secinfo->sec->flags |= SEC_EXCLUDE;
8550eb6e
JJ
769 }
770
b34976b6 771 return TRUE;
f5fa8ca2
JJ
772}
773
774/* Write out the merged section. */
775
b34976b6 776bfd_boolean
ac0e732e 777_bfd_write_merged_section (bfd *output_bfd, asection *sec, void *psecinfo)
f5fa8ca2
JJ
778{
779 struct sec_merge_sec_info *secinfo;
dc810e39 780 file_ptr pos;
f5fa8ca2
JJ
781
782 secinfo = (struct sec_merge_sec_info *) psecinfo;
783
57ceae94 784 if (secinfo->first_str == NULL)
b34976b6 785 return TRUE;
f5fa8ca2 786
dc810e39
AM
787 pos = sec->output_section->filepos + sec->output_offset;
788 if (bfd_seek (output_bfd, pos, SEEK_SET) != 0)
b34976b6 789 return FALSE;
f5fa8ca2 790
57ceae94 791 if (! sec_merge_emit (output_bfd, secinfo->first_str))
b34976b6 792 return FALSE;
f5fa8ca2 793
b34976b6 794 return TRUE;
f5fa8ca2
JJ
795}
796
797/* Adjust an address in the SEC_MERGE section. Given OFFSET within
798 *PSEC, this returns the new offset in the adjusted SEC_MERGE
799 section and writes the new section back into *PSEC. */
800
801bfd_vma
ac0e732e 802_bfd_merged_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED, asection **psec,
753731ee 803 void *psecinfo, bfd_vma offset)
f5fa8ca2
JJ
804{
805 struct sec_merge_sec_info *secinfo;
806 struct sec_merge_hash_entry *entry;
807 unsigned char *p;
808 asection *sec = *psec;
809
810 secinfo = (struct sec_merge_sec_info *) psecinfo;
811
eea6121a 812 if (offset >= sec->rawsize)
f5fa8ca2 813 {
eea6121a 814 if (offset > sec->rawsize)
923f08ff
AM
815 {
816 (*_bfd_error_handler)
753731ee
AM
817 (_("%s: access beyond end of merged section (%ld)"),
818 bfd_get_filename (sec->owner), (long) offset);
923f08ff 819 }
eea6121a 820 return secinfo->first_str ? sec->size : 0;
f5fa8ca2
JJ
821 }
822
823 if (secinfo->htab->strings)
824 {
825 if (sec->entsize == 1)
826 {
753731ee 827 p = secinfo->contents + offset - 1;
894bb1ee 828 while (p >= secinfo->contents && *p)
f5fa8ca2
JJ
829 --p;
830 ++p;
831 }
832 else
833 {
753731ee 834 p = secinfo->contents + (offset / sec->entsize) * sec->entsize;
f5fa8ca2
JJ
835 p -= sec->entsize;
836 while (p >= secinfo->contents)
837 {
838 unsigned int i;
839
840 for (i = 0; i < sec->entsize; ++i)
841 if (p[i] != '\0')
842 break;
843 if (i == sec->entsize)
844 break;
845 p -= sec->entsize;
846 }
847 p += sec->entsize;
848 }
849 }
850 else
851 {
753731ee 852 p = secinfo->contents + (offset / sec->entsize) * sec->entsize;
f5fa8ca2 853 }
f075ee0c 854 entry = sec_merge_hash_lookup (secinfo->htab, (char *) p, 0, FALSE);
f5fa8ca2
JJ
855 if (!entry)
856 {
857 if (! secinfo->htab->strings)
858 abort ();
859 /* This should only happen if somebody points into the padding
860 after a NUL character but before next entity. */
861 if (*p)
862 abort ();
863 if (! secinfo->htab->first)
864 abort ();
865 entry = secinfo->htab->first;
753731ee
AM
866 p = (secinfo->contents + (offset / sec->entsize + 1) * sec->entsize
867 - entry->len);
f5fa8ca2
JJ
868 }
869
8550eb6e
JJ
870 *psec = entry->secinfo->sec;
871 return entry->u.index + (secinfo->contents + offset - p);
f5fa8ca2 872}
This page took 0.287993 seconds and 4 git commands to generate.