]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/merge.c
bfd/
[thirdparty/binutils-gdb.git] / bfd / merge.c
CommitLineData
f5fa8ca2 1/* SEC_MERGE support.
eea6121a 2 Copyright 2001, 2002, 2003, 2004 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
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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
244 if (! bfd_hash_table_init (&table->table, sec_merge_hash_newfunc))
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
JJ
265{
266 register struct sec_merge_hash_entry *entry;
267
b34976b6 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;
f5fa8ca2 291 char *pad = "";
a531bbd2 292 bfd_size_type off = 0;
57ceae94 293 int alignment_power = sec->output_section->alignment_power;
f5fa8ca2 294
a531bbd2 295 if (alignment_power)
dc810e39 296 pad = bfd_zmalloc ((bfd_size_type) 1 << alignment_power);
f5fa8ca2 297
8550eb6e 298 for (; entry != NULL && entry->secinfo == secinfo; entry = entry->next)
f5fa8ca2
JJ
299 {
300 register const char *str;
301 register size_t len;
302
a531bbd2
JJ
303 len = off & (entry->alignment - 1);
304 if (len)
305 {
306 len = entry->alignment - len;
57ceae94 307 if (bfd_bwrite (pad, len, abfd) != len)
a531bbd2
JJ
308 break;
309 off += len;
310 }
311
f5fa8ca2
JJ
312 str = entry->root.string;
313 len = entry->len;
314
57ceae94 315 if (bfd_bwrite (str, len, abfd) != len)
f5fa8ca2
JJ
316 break;
317
a531bbd2 318 off += len;
f5fa8ca2
JJ
319 }
320
a531bbd2 321 if (alignment_power)
f5fa8ca2
JJ
322 free (pad);
323
b34976b6 324 return entry == NULL || entry->secinfo != secinfo;
f5fa8ca2
JJ
325}
326
57ceae94
AM
327/* Register a SEC_MERGE section as a candidate for merging.
328 This function is called for all non-dynamic SEC_MERGE input sections. */
f5fa8ca2 329
b34976b6 330bfd_boolean
57ceae94
AM
331_bfd_add_merge_section (bfd *abfd, void **psinfo, asection *sec,
332 void **psecinfo)
f5fa8ca2 333{
f5fa8ca2
JJ
334 struct sec_merge_info *sinfo;
335 struct sec_merge_sec_info *secinfo;
f5fa8ca2 336 unsigned int align;
dc810e39 337 bfd_size_type amt;
f5fa8ca2 338
57ceae94
AM
339 if ((abfd->flags & DYNAMIC) != 0
340 || (sec->flags & SEC_MERGE) == 0)
341 abort ();
342
eea6121a 343 if (sec->size == 0
57ceae94 344 || (sec->flags & SEC_EXCLUDE) != 0
f5fa8ca2 345 || sec->entsize == 0)
b34976b6 346 return TRUE;
f5fa8ca2
JJ
347
348 if ((sec->flags & SEC_RELOC) != 0)
349 {
350 /* We aren't prepared to handle relocations in merged sections. */
b34976b6 351 return TRUE;
f5fa8ca2
JJ
352 }
353
57ceae94
AM
354 align = sec->alignment_power;
355 if ((sec->entsize < (unsigned) 1 << align
a531bbd2
JJ
356 && ((sec->entsize & (sec->entsize - 1))
357 || !(sec->flags & SEC_STRINGS)))
57ceae94
AM
358 || (sec->entsize > (unsigned) 1 << align
359 && (sec->entsize & (((unsigned) 1 << align) - 1))))
f5fa8ca2
JJ
360 {
361 /* Sanity check. If string character size is smaller than
362 alignment, then we require character size to be a power
363 of 2, otherwise character size must be integer multiple
a531bbd2
JJ
364 of alignment. For non-string constants, alignment must
365 be smaller than or equal to entity size and entity size
366 must be integer multiple of alignment. */
b34976b6 367 return TRUE;
f5fa8ca2
JJ
368 }
369
f5fa8ca2 370 for (sinfo = (struct sec_merge_info *) *psinfo; sinfo; sinfo = sinfo->next)
8550eb6e
JJ
371 if ((secinfo = sinfo->chain)
372 && ! ((secinfo->sec->flags ^ sec->flags) & (SEC_MERGE | SEC_STRINGS))
373 && secinfo->sec->entsize == sec->entsize
57ceae94
AM
374 && secinfo->sec->alignment_power == sec->alignment_power
375 && secinfo->sec->output_section == sec->output_section)
f5fa8ca2
JJ
376 break;
377
378 if (sinfo == NULL)
379 {
380 /* Initialize the information we need to keep track of. */
57ceae94 381 sinfo = bfd_alloc (abfd, sizeof (struct sec_merge_info));
f5fa8ca2
JJ
382 if (sinfo == NULL)
383 goto error_return;
384 sinfo->next = (struct sec_merge_info *) *psinfo;
8550eb6e 385 sinfo->chain = NULL;
ac0e732e 386 *psinfo = sinfo;
699cb9b8 387 sinfo->htab = sec_merge_init (sec->entsize, (sec->flags & SEC_STRINGS));
f5fa8ca2
JJ
388 if (sinfo->htab == NULL)
389 goto error_return;
390 }
391
392 /* Read the section from abfd. */
393
eea6121a 394 amt = sizeof (struct sec_merge_sec_info) + sec->size - 1;
dc810e39 395 *psecinfo = bfd_alloc (abfd, amt);
f5fa8ca2
JJ
396 if (*psecinfo == NULL)
397 goto error_return;
398
57ceae94 399 secinfo = (struct sec_merge_sec_info *) *psecinfo;
8550eb6e
JJ
400 if (sinfo->chain)
401 {
402 secinfo->next = sinfo->chain->next;
403 sinfo->chain->next = secinfo;
404 }
405 else
406 secinfo->next = secinfo;
407 sinfo->chain = secinfo;
408 secinfo->sec = sec;
409 secinfo->psecinfo = psecinfo;
f5fa8ca2 410 secinfo->htab = sinfo->htab;
57ceae94 411 secinfo->first_str = NULL;
f5fa8ca2 412
eea6121a 413 sec->rawsize = sec->size;
dc810e39 414 if (! bfd_get_section_contents (sec->owner, sec, secinfo->contents,
eea6121a 415 0, sec->size))
f5fa8ca2
JJ
416 goto error_return;
417
b34976b6 418 return TRUE;
8550eb6e
JJ
419
420 error_return:
421 *psecinfo = NULL;
b34976b6 422 return FALSE;
8550eb6e
JJ
423}
424
8550eb6e 425/* Record one section into the hash table. */
b34976b6 426static bfd_boolean
ac0e732e
AJ
427record_section (struct sec_merge_info *sinfo,
428 struct sec_merge_sec_info *secinfo)
8550eb6e
JJ
429{
430 asection *sec = secinfo->sec;
431 struct sec_merge_hash_entry *entry;
b34976b6 432 bfd_boolean nul;
8550eb6e
JJ
433 unsigned char *p, *end;
434 bfd_vma mask, eltalign;
435 unsigned int align, i;
436
57ceae94 437 align = sec->alignment_power;
eea6121a 438 end = secinfo->contents + sec->size;
b34976b6 439 nul = FALSE;
dc810e39 440 mask = ((bfd_vma) 1 << align) - 1;
f5fa8ca2
JJ
441 if (sec->flags & SEC_STRINGS)
442 {
dc810e39 443 for (p = secinfo->contents; p < end; )
f5fa8ca2 444 {
a531bbd2
JJ
445 eltalign = p - secinfo->contents;
446 eltalign = ((eltalign ^ (eltalign - 1)) + 1) >> 1;
447 if (!eltalign || eltalign > mask)
448 eltalign = mask + 1;
dc810e39 449 entry = sec_merge_add (sinfo->htab, p, (unsigned) eltalign, secinfo);
8550eb6e
JJ
450 if (! entry)
451 goto error_return;
f5fa8ca2
JJ
452 p += entry->len;
453 if (sec->entsize == 1)
454 {
455 while (p < end && *p == 0)
456 {
457 if (!nul && !((p - secinfo->contents) & mask))
458 {
b34976b6 459 nul = TRUE;
dc810e39
AM
460 entry = sec_merge_add (sinfo->htab, "",
461 (unsigned) mask + 1, secinfo);
8550eb6e
JJ
462 if (! entry)
463 goto error_return;
f5fa8ca2
JJ
464 }
465 p++;
ddb2b442 466 }
f5fa8ca2
JJ
467 }
468 else
469 {
470 while (p < end)
471 {
472 for (i = 0; i < sec->entsize; i++)
473 if (p[i] != '\0')
474 break;
475 if (i != sec->entsize)
476 break;
477 if (!nul && !((p - secinfo->contents) & mask))
478 {
b34976b6 479 nul = TRUE;
dc810e39
AM
480 entry = sec_merge_add (sinfo->htab, p,
481 (unsigned) mask + 1, secinfo);
8550eb6e
JJ
482 if (! entry)
483 goto error_return;
f5fa8ca2
JJ
484 }
485 p += sec->entsize;
486 }
487 }
488 }
489 }
490 else
491 {
492 for (p = secinfo->contents; p < end; p += sec->entsize)
493 {
8550eb6e
JJ
494 entry = sec_merge_add (sinfo->htab, p, 1, secinfo);
495 if (! entry)
496 goto error_return;
497 }
498 }
499
b34976b6 500 return TRUE;
8550eb6e
JJ
501
502error_return:
503 for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
504 *secinfo->psecinfo = NULL;
b34976b6 505 return FALSE;
8550eb6e
JJ
506}
507
ddb2b442
AM
508static int
509strrevcmp (const void *a, const void *b)
510{
511 struct sec_merge_hash_entry *A = *(struct sec_merge_hash_entry **) a;
512 struct sec_merge_hash_entry *B = *(struct sec_merge_hash_entry **) b;
513 unsigned int lenA = A->len;
514 unsigned int lenB = B->len;
515 const unsigned char *s = A->root.string + lenA - 1;
516 const unsigned char *t = B->root.string + lenB - 1;
517 int l = lenA < lenB ? lenA : lenB;
518
519 while (l)
520 {
521 if (*s != *t)
522 return (int) *s - (int) *t;
523 s--;
524 t--;
525 l--;
526 }
527 return lenA - lenB;
528}
529
530/* Like strrevcmp, but for the case where all strings have the same
531 alignment > entsize. */
532
533static int
534strrevcmp_align (const void *a, const void *b)
535{
536 struct sec_merge_hash_entry *A = *(struct sec_merge_hash_entry **) a;
537 struct sec_merge_hash_entry *B = *(struct sec_merge_hash_entry **) b;
538 unsigned int lenA = A->len;
539 unsigned int lenB = B->len;
540 const unsigned char *s = A->root.string + lenA - 1;
541 const unsigned char *t = B->root.string + lenB - 1;
542 int l = lenA < lenB ? lenA : lenB;
543 int tail_align = (lenA & (A->alignment - 1)) - (lenB & (A->alignment - 1));
544
545 if (tail_align != 0)
546 return tail_align;
547
548 while (l)
549 {
550 if (*s != *t)
551 return (int) *s - (int) *t;
552 s--;
553 t--;
554 l--;
555 }
556 return lenA - lenB;
557}
558
559static inline int
560is_suffix (const struct sec_merge_hash_entry *A,
561 const struct sec_merge_hash_entry *B)
562{
563 if (A->len <= B->len)
564 /* B cannot be a suffix of A unless A is equal to B, which is guaranteed
565 not to be equal by the hash table. */
566 return 0;
567
568 return memcmp (A->root.string + (A->len - B->len),
569 B->root.string, B->len) == 0;
570}
571
8550eb6e
JJ
572/* This is a helper function for _bfd_merge_sections. It attempts to
573 merge strings matching suffixes of longer strings. */
574static void
ac0e732e 575merge_strings (struct sec_merge_info *sinfo)
8550eb6e 576{
ddb2b442 577 struct sec_merge_hash_entry **array, **a, *e;
8550eb6e 578 struct sec_merge_sec_info *secinfo;
dc810e39 579 bfd_size_type size, amt;
ddb2b442 580 unsigned int alignment = 0;
8550eb6e 581
ddb2b442 582 /* Now sort the strings */
dc810e39 583 amt = sinfo->htab->size * sizeof (struct sec_merge_hash_entry *);
57ceae94 584 array = bfd_malloc (amt);
8550eb6e
JJ
585 if (array == NULL)
586 goto alloc_failure;
587
588 for (e = sinfo->htab->first, a = array; e; e = e->next)
589 if (e->alignment)
ddb2b442
AM
590 {
591 *a++ = e;
592 /* Adjust the length to not include the zero terminator. */
593 e->len -= sinfo->htab->entsize;
594 if (alignment != e->alignment)
595 {
596 if (alignment == 0)
597 alignment = e->alignment;
598 else
599 alignment = (unsigned) -1;
600 }
601 }
8550eb6e
JJ
602
603 sinfo->htab->size = a - array;
ddb2b442 604 if (sinfo->htab->size != 0)
8550eb6e 605 {
ddb2b442
AM
606 qsort (array, (size_t) sinfo->htab->size,
607 sizeof (struct sec_merge_hash_entry *),
608 (alignment != (unsigned) -1 && alignment > sinfo->htab->entsize
609 ? strrevcmp_align : strrevcmp));
610
611 /* Loop over the sorted array and merge suffixes */
612 e = *--a;
613 e->len += sinfo->htab->entsize;
614 while (--a >= array)
8550eb6e 615 {
ddb2b442 616 struct sec_merge_hash_entry *cmp = *a;
8550eb6e 617
ddb2b442
AM
618 cmp->len += sinfo->htab->entsize;
619 if (e->alignment >= cmp->alignment
620 && !((e->len - cmp->len) & (cmp->alignment - 1))
621 && is_suffix (e, cmp))
622 {
623 cmp->u.suffix = e;
624 cmp->alignment = 0;
f5fa8ca2 625 }
8550eb6e 626 else
ddb2b442 627 e = cmp;
8550eb6e 628 }
f5fa8ca2
JJ
629 }
630
8550eb6e
JJ
631alloc_failure:
632 if (array)
633 free (array);
8550eb6e
JJ
634
635 /* Now assign positions to the strings we want to keep. */
636 size = 0;
637 secinfo = sinfo->htab->first->secinfo;
638 for (e = sinfo->htab->first; e; e = e->next)
639 {
640 if (e->secinfo != secinfo)
641 {
eea6121a 642 secinfo->sec->size = size;
8550eb6e
JJ
643 secinfo = e->secinfo;
644 }
645 if (e->alignment)
646 {
57ceae94 647 if (e->secinfo->first_str == NULL)
8550eb6e 648 {
57ceae94 649 e->secinfo->first_str = e;
8550eb6e
JJ
650 size = 0;
651 }
652 size = (size + e->alignment - 1) & ~((bfd_vma) e->alignment - 1);
653 e->u.index = size;
654 size += e->len;
655 }
656 }
eea6121a 657 secinfo->sec->size = size;
8550eb6e
JJ
658
659 /* And now adjust the rest, removing them from the chain (but not hashtable)
660 at the same time. */
661 for (a = &sinfo->htab->first, e = *a; e; e = e->next)
662 if (e->alignment)
663 a = &e->next;
664 else
665 {
666 *a = e->next;
667 if (e->len)
668 {
669 e->secinfo = e->u.suffix->secinfo;
670 e->alignment = e->u.suffix->alignment;
671 e->u.index = e->u.suffix->u.index + (e->u.suffix->len - e->len);
672 }
673 }
674}
f5fa8ca2 675
8550eb6e
JJ
676/* This function is called once after all SEC_MERGE sections are registered
677 with _bfd_merge_section. */
678
b34976b6 679bfd_boolean
57ceae94
AM
680_bfd_merge_sections (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info,
681 void *xsinfo, void (*remove_hook) (bfd *, asection *))
8550eb6e
JJ
682{
683 struct sec_merge_info *sinfo;
684
685 for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next)
686 {
687 struct sec_merge_sec_info * secinfo;
688
689 if (! sinfo->chain)
690 continue;
691
692 /* Move sinfo->chain to head of the chain, terminate it. */
693 secinfo = sinfo->chain;
694 sinfo->chain = secinfo->next;
695 secinfo->next = NULL;
696
697 /* Record the sections into the hash table. */
698 for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
699 if (secinfo->sec->flags & SEC_EXCLUDE)
d3c456e9
JJ
700 {
701 *secinfo->psecinfo = NULL;
702 if (remove_hook)
703 (*remove_hook) (abfd, secinfo->sec);
704 }
8550eb6e
JJ
705 else if (! record_section (sinfo, secinfo))
706 break;
707
708 if (secinfo)
709 continue;
710
86eaf01e
JJ
711 if (sinfo->htab->first == NULL)
712 continue;
713
8550eb6e
JJ
714 if (sinfo->htab->strings)
715 merge_strings (sinfo);
716 else
717 {
718 struct sec_merge_hash_entry *e;
719 bfd_size_type size = 0;
720
721 /* Things are much simpler for non-strings.
722 Just assign them slots in the section. */
723 secinfo = NULL;
724 for (e = sinfo->htab->first; e; e = e->next)
725 {
57ceae94 726 if (e->secinfo->first_str == NULL)
8550eb6e
JJ
727 {
728 if (secinfo)
eea6121a 729 secinfo->sec->size = size;
57ceae94 730 e->secinfo->first_str = e;
8550eb6e
JJ
731 size = 0;
732 }
733 size = (size + e->alignment - 1)
734 & ~((bfd_vma) e->alignment - 1);
735 e->u.index = size;
736 size += e->len;
737 secinfo = e->secinfo;
738 }
eea6121a 739 secinfo->sec->size = size;
8550eb6e
JJ
740 }
741
27c630ba 742 /* Finally remove all input sections which have not made it into
8550eb6e
JJ
743 the hash table at all. */
744 for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
57ceae94
AM
745 if (secinfo->first_str == NULL)
746 _bfd_strip_section_from_output (info, secinfo->sec);
8550eb6e
JJ
747 }
748
b34976b6 749 return TRUE;
f5fa8ca2
JJ
750}
751
752/* Write out the merged section. */
753
b34976b6 754bfd_boolean
ac0e732e 755_bfd_write_merged_section (bfd *output_bfd, asection *sec, void *psecinfo)
f5fa8ca2
JJ
756{
757 struct sec_merge_sec_info *secinfo;
dc810e39 758 file_ptr pos;
f5fa8ca2
JJ
759
760 secinfo = (struct sec_merge_sec_info *) psecinfo;
761
57ceae94 762 if (secinfo->first_str == NULL)
b34976b6 763 return TRUE;
f5fa8ca2 764
dc810e39
AM
765 pos = sec->output_section->filepos + sec->output_offset;
766 if (bfd_seek (output_bfd, pos, SEEK_SET) != 0)
b34976b6 767 return FALSE;
f5fa8ca2 768
57ceae94 769 if (! sec_merge_emit (output_bfd, secinfo->first_str))
b34976b6 770 return FALSE;
f5fa8ca2 771
b34976b6 772 return TRUE;
f5fa8ca2
JJ
773}
774
775/* Adjust an address in the SEC_MERGE section. Given OFFSET within
776 *PSEC, this returns the new offset in the adjusted SEC_MERGE
777 section and writes the new section back into *PSEC. */
778
779bfd_vma
ac0e732e 780_bfd_merged_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED, asection **psec,
753731ee 781 void *psecinfo, bfd_vma offset)
f5fa8ca2
JJ
782{
783 struct sec_merge_sec_info *secinfo;
784 struct sec_merge_hash_entry *entry;
785 unsigned char *p;
786 asection *sec = *psec;
787
788 secinfo = (struct sec_merge_sec_info *) psecinfo;
789
eea6121a 790 if (offset >= sec->rawsize)
f5fa8ca2 791 {
eea6121a 792 if (offset > sec->rawsize)
923f08ff
AM
793 {
794 (*_bfd_error_handler)
753731ee
AM
795 (_("%s: access beyond end of merged section (%ld)"),
796 bfd_get_filename (sec->owner), (long) offset);
923f08ff 797 }
eea6121a 798 return secinfo->first_str ? sec->size : 0;
f5fa8ca2
JJ
799 }
800
801 if (secinfo->htab->strings)
802 {
803 if (sec->entsize == 1)
804 {
753731ee 805 p = secinfo->contents + offset - 1;
894bb1ee 806 while (p >= secinfo->contents && *p)
f5fa8ca2
JJ
807 --p;
808 ++p;
809 }
810 else
811 {
753731ee 812 p = secinfo->contents + (offset / sec->entsize) * sec->entsize;
f5fa8ca2
JJ
813 p -= sec->entsize;
814 while (p >= secinfo->contents)
815 {
816 unsigned int i;
817
818 for (i = 0; i < sec->entsize; ++i)
819 if (p[i] != '\0')
820 break;
821 if (i == sec->entsize)
822 break;
823 p -= sec->entsize;
824 }
825 p += sec->entsize;
826 }
827 }
828 else
829 {
753731ee 830 p = secinfo->contents + (offset / sec->entsize) * sec->entsize;
f5fa8ca2 831 }
b34976b6 832 entry = sec_merge_hash_lookup (secinfo->htab, p, 0, FALSE);
f5fa8ca2
JJ
833 if (!entry)
834 {
835 if (! secinfo->htab->strings)
836 abort ();
837 /* This should only happen if somebody points into the padding
838 after a NUL character but before next entity. */
839 if (*p)
840 abort ();
841 if (! secinfo->htab->first)
842 abort ();
843 entry = secinfo->htab->first;
753731ee
AM
844 p = (secinfo->contents + (offset / sec->entsize + 1) * sec->entsize
845 - entry->len);
f5fa8ca2
JJ
846 }
847
8550eb6e
JJ
848 *psec = entry->secinfo->sec;
849 return entry->u.index + (secinfo->contents + offset - p);
f5fa8ca2 850}