bfd/
[deliverable/binutils-gdb.git] / bfd / merge.c
CommitLineData
f5fa8ca2 1/* SEC_MERGE support.
ac0e732e 2 Copyright 2001, 2002, 2003 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
f5fa8ca2 343 if (sec->_raw_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
dc810e39
AM
394 amt = sizeof (struct sec_merge_sec_info) + sec->_raw_size - 1;
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
dc810e39 413 if (! bfd_get_section_contents (sec->owner, sec, secinfo->contents,
57ceae94 414 0, sec->_raw_size))
f5fa8ca2
JJ
415 goto error_return;
416
b34976b6 417 return TRUE;
8550eb6e
JJ
418
419 error_return:
420 *psecinfo = NULL;
b34976b6 421 return FALSE;
8550eb6e
JJ
422}
423
8550eb6e 424/* Record one section into the hash table. */
b34976b6 425static bfd_boolean
ac0e732e
AJ
426record_section (struct sec_merge_info *sinfo,
427 struct sec_merge_sec_info *secinfo)
8550eb6e
JJ
428{
429 asection *sec = secinfo->sec;
430 struct sec_merge_hash_entry *entry;
b34976b6 431 bfd_boolean nul;
8550eb6e
JJ
432 unsigned char *p, *end;
433 bfd_vma mask, eltalign;
434 unsigned int align, i;
435
57ceae94 436 align = sec->alignment_power;
f5fa8ca2 437 end = secinfo->contents + sec->_raw_size;
b34976b6 438 nul = FALSE;
dc810e39 439 mask = ((bfd_vma) 1 << align) - 1;
f5fa8ca2
JJ
440 if (sec->flags & SEC_STRINGS)
441 {
dc810e39 442 for (p = secinfo->contents; p < end; )
f5fa8ca2 443 {
a531bbd2
JJ
444 eltalign = p - secinfo->contents;
445 eltalign = ((eltalign ^ (eltalign - 1)) + 1) >> 1;
446 if (!eltalign || eltalign > mask)
447 eltalign = mask + 1;
dc810e39 448 entry = sec_merge_add (sinfo->htab, p, (unsigned) eltalign, secinfo);
8550eb6e
JJ
449 if (! entry)
450 goto error_return;
f5fa8ca2
JJ
451 p += entry->len;
452 if (sec->entsize == 1)
453 {
454 while (p < end && *p == 0)
455 {
456 if (!nul && !((p - secinfo->contents) & mask))
457 {
b34976b6 458 nul = TRUE;
dc810e39
AM
459 entry = sec_merge_add (sinfo->htab, "",
460 (unsigned) mask + 1, secinfo);
8550eb6e
JJ
461 if (! entry)
462 goto error_return;
f5fa8ca2
JJ
463 }
464 p++;
ddb2b442 465 }
f5fa8ca2
JJ
466 }
467 else
468 {
469 while (p < end)
470 {
471 for (i = 0; i < sec->entsize; i++)
472 if (p[i] != '\0')
473 break;
474 if (i != sec->entsize)
475 break;
476 if (!nul && !((p - secinfo->contents) & mask))
477 {
b34976b6 478 nul = TRUE;
dc810e39
AM
479 entry = sec_merge_add (sinfo->htab, p,
480 (unsigned) mask + 1, secinfo);
8550eb6e
JJ
481 if (! entry)
482 goto error_return;
f5fa8ca2
JJ
483 }
484 p += sec->entsize;
485 }
486 }
487 }
488 }
489 else
490 {
491 for (p = secinfo->contents; p < end; p += sec->entsize)
492 {
8550eb6e
JJ
493 entry = sec_merge_add (sinfo->htab, p, 1, secinfo);
494 if (! entry)
495 goto error_return;
496 }
497 }
498
b34976b6 499 return TRUE;
8550eb6e
JJ
500
501error_return:
502 for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
503 *secinfo->psecinfo = NULL;
b34976b6 504 return FALSE;
8550eb6e
JJ
505}
506
ddb2b442
AM
507static int
508strrevcmp (const void *a, const void *b)
509{
510 struct sec_merge_hash_entry *A = *(struct sec_merge_hash_entry **) a;
511 struct sec_merge_hash_entry *B = *(struct sec_merge_hash_entry **) b;
512 unsigned int lenA = A->len;
513 unsigned int lenB = B->len;
514 const unsigned char *s = A->root.string + lenA - 1;
515 const unsigned char *t = B->root.string + lenB - 1;
516 int l = lenA < lenB ? lenA : lenB;
517
518 while (l)
519 {
520 if (*s != *t)
521 return (int) *s - (int) *t;
522 s--;
523 t--;
524 l--;
525 }
526 return lenA - lenB;
527}
528
529/* Like strrevcmp, but for the case where all strings have the same
530 alignment > entsize. */
531
532static int
533strrevcmp_align (const void *a, const void *b)
534{
535 struct sec_merge_hash_entry *A = *(struct sec_merge_hash_entry **) a;
536 struct sec_merge_hash_entry *B = *(struct sec_merge_hash_entry **) b;
537 unsigned int lenA = A->len;
538 unsigned int lenB = B->len;
539 const unsigned char *s = A->root.string + lenA - 1;
540 const unsigned char *t = B->root.string + lenB - 1;
541 int l = lenA < lenB ? lenA : lenB;
542 int tail_align = (lenA & (A->alignment - 1)) - (lenB & (A->alignment - 1));
543
544 if (tail_align != 0)
545 return tail_align;
546
547 while (l)
548 {
549 if (*s != *t)
550 return (int) *s - (int) *t;
551 s--;
552 t--;
553 l--;
554 }
555 return lenA - lenB;
556}
557
558static inline int
559is_suffix (const struct sec_merge_hash_entry *A,
560 const struct sec_merge_hash_entry *B)
561{
562 if (A->len <= B->len)
563 /* B cannot be a suffix of A unless A is equal to B, which is guaranteed
564 not to be equal by the hash table. */
565 return 0;
566
567 return memcmp (A->root.string + (A->len - B->len),
568 B->root.string, B->len) == 0;
569}
570
8550eb6e
JJ
571/* This is a helper function for _bfd_merge_sections. It attempts to
572 merge strings matching suffixes of longer strings. */
573static void
ac0e732e 574merge_strings (struct sec_merge_info *sinfo)
8550eb6e 575{
ddb2b442 576 struct sec_merge_hash_entry **array, **a, *e;
8550eb6e 577 struct sec_merge_sec_info *secinfo;
dc810e39 578 bfd_size_type size, amt;
ddb2b442 579 unsigned int alignment = 0;
8550eb6e 580
ddb2b442 581 /* Now sort the strings */
dc810e39 582 amt = sinfo->htab->size * sizeof (struct sec_merge_hash_entry *);
57ceae94 583 array = bfd_malloc (amt);
8550eb6e
JJ
584 if (array == NULL)
585 goto alloc_failure;
586
587 for (e = sinfo->htab->first, a = array; e; e = e->next)
588 if (e->alignment)
ddb2b442
AM
589 {
590 *a++ = e;
591 /* Adjust the length to not include the zero terminator. */
592 e->len -= sinfo->htab->entsize;
593 if (alignment != e->alignment)
594 {
595 if (alignment == 0)
596 alignment = e->alignment;
597 else
598 alignment = (unsigned) -1;
599 }
600 }
8550eb6e
JJ
601
602 sinfo->htab->size = a - array;
ddb2b442 603 if (sinfo->htab->size != 0)
8550eb6e 604 {
ddb2b442
AM
605 qsort (array, (size_t) sinfo->htab->size,
606 sizeof (struct sec_merge_hash_entry *),
607 (alignment != (unsigned) -1 && alignment > sinfo->htab->entsize
608 ? strrevcmp_align : strrevcmp));
609
610 /* Loop over the sorted array and merge suffixes */
611 e = *--a;
612 e->len += sinfo->htab->entsize;
613 while (--a >= array)
8550eb6e 614 {
ddb2b442 615 struct sec_merge_hash_entry *cmp = *a;
8550eb6e 616
ddb2b442
AM
617 cmp->len += sinfo->htab->entsize;
618 if (e->alignment >= cmp->alignment
619 && !((e->len - cmp->len) & (cmp->alignment - 1))
620 && is_suffix (e, cmp))
621 {
622 cmp->u.suffix = e;
623 cmp->alignment = 0;
f5fa8ca2 624 }
8550eb6e 625 else
ddb2b442 626 e = cmp;
8550eb6e 627 }
f5fa8ca2
JJ
628 }
629
8550eb6e
JJ
630alloc_failure:
631 if (array)
632 free (array);
8550eb6e
JJ
633
634 /* Now assign positions to the strings we want to keep. */
635 size = 0;
636 secinfo = sinfo->htab->first->secinfo;
637 for (e = sinfo->htab->first; e; e = e->next)
638 {
639 if (e->secinfo != secinfo)
640 {
641 secinfo->sec->_cooked_size = size;
642 secinfo = e->secinfo;
643 }
644 if (e->alignment)
645 {
57ceae94 646 if (e->secinfo->first_str == NULL)
8550eb6e 647 {
57ceae94 648 e->secinfo->first_str = e;
8550eb6e
JJ
649 size = 0;
650 }
651 size = (size + e->alignment - 1) & ~((bfd_vma) e->alignment - 1);
652 e->u.index = size;
653 size += e->len;
654 }
655 }
656 secinfo->sec->_cooked_size = size;
657
658 /* And now adjust the rest, removing them from the chain (but not hashtable)
659 at the same time. */
660 for (a = &sinfo->htab->first, e = *a; e; e = e->next)
661 if (e->alignment)
662 a = &e->next;
663 else
664 {
665 *a = e->next;
666 if (e->len)
667 {
668 e->secinfo = e->u.suffix->secinfo;
669 e->alignment = e->u.suffix->alignment;
670 e->u.index = e->u.suffix->u.index + (e->u.suffix->len - e->len);
671 }
672 }
673}
f5fa8ca2 674
8550eb6e
JJ
675/* This function is called once after all SEC_MERGE sections are registered
676 with _bfd_merge_section. */
677
b34976b6 678bfd_boolean
57ceae94
AM
679_bfd_merge_sections (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info,
680 void *xsinfo, void (*remove_hook) (bfd *, asection *))
8550eb6e
JJ
681{
682 struct sec_merge_info *sinfo;
683
684 for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next)
685 {
686 struct sec_merge_sec_info * secinfo;
687
688 if (! sinfo->chain)
689 continue;
690
691 /* Move sinfo->chain to head of the chain, terminate it. */
692 secinfo = sinfo->chain;
693 sinfo->chain = secinfo->next;
694 secinfo->next = NULL;
695
696 /* Record the sections into the hash table. */
697 for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
698 if (secinfo->sec->flags & SEC_EXCLUDE)
d3c456e9
JJ
699 {
700 *secinfo->psecinfo = NULL;
701 if (remove_hook)
702 (*remove_hook) (abfd, secinfo->sec);
703 }
8550eb6e
JJ
704 else if (! record_section (sinfo, secinfo))
705 break;
706
707 if (secinfo)
708 continue;
709
86eaf01e
JJ
710 if (sinfo->htab->first == NULL)
711 continue;
712
8550eb6e
JJ
713 if (sinfo->htab->strings)
714 merge_strings (sinfo);
715 else
716 {
717 struct sec_merge_hash_entry *e;
718 bfd_size_type size = 0;
719
720 /* Things are much simpler for non-strings.
721 Just assign them slots in the section. */
722 secinfo = NULL;
723 for (e = sinfo->htab->first; e; e = e->next)
724 {
57ceae94 725 if (e->secinfo->first_str == NULL)
8550eb6e
JJ
726 {
727 if (secinfo)
728 secinfo->sec->_cooked_size = size;
57ceae94 729 e->secinfo->first_str = e;
8550eb6e
JJ
730 size = 0;
731 }
732 size = (size + e->alignment - 1)
733 & ~((bfd_vma) e->alignment - 1);
734 e->u.index = size;
735 size += e->len;
736 secinfo = e->secinfo;
737 }
738 secinfo->sec->_cooked_size = size;
739 }
740
27c630ba 741 /* Finally remove all input sections which have not made it into
8550eb6e
JJ
742 the hash table at all. */
743 for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
57ceae94
AM
744 if (secinfo->first_str == NULL)
745 _bfd_strip_section_from_output (info, secinfo->sec);
8550eb6e
JJ
746 }
747
b34976b6 748 return TRUE;
f5fa8ca2
JJ
749}
750
751/* Write out the merged section. */
752
b34976b6 753bfd_boolean
ac0e732e 754_bfd_write_merged_section (bfd *output_bfd, asection *sec, void *psecinfo)
f5fa8ca2
JJ
755{
756 struct sec_merge_sec_info *secinfo;
dc810e39 757 file_ptr pos;
f5fa8ca2
JJ
758
759 secinfo = (struct sec_merge_sec_info *) psecinfo;
760
57ceae94 761 if (secinfo->first_str == NULL)
b34976b6 762 return TRUE;
f5fa8ca2 763
dc810e39
AM
764 pos = sec->output_section->filepos + sec->output_offset;
765 if (bfd_seek (output_bfd, pos, SEEK_SET) != 0)
b34976b6 766 return FALSE;
f5fa8ca2 767
57ceae94 768 if (! sec_merge_emit (output_bfd, secinfo->first_str))
b34976b6 769 return FALSE;
f5fa8ca2 770
b34976b6 771 return TRUE;
f5fa8ca2
JJ
772}
773
774/* Adjust an address in the SEC_MERGE section. Given OFFSET within
775 *PSEC, this returns the new offset in the adjusted SEC_MERGE
776 section and writes the new section back into *PSEC. */
777
778bfd_vma
ac0e732e 779_bfd_merged_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED, asection **psec,
753731ee 780 void *psecinfo, bfd_vma offset)
f5fa8ca2
JJ
781{
782 struct sec_merge_sec_info *secinfo;
783 struct sec_merge_hash_entry *entry;
784 unsigned char *p;
785 asection *sec = *psec;
786
787 secinfo = (struct sec_merge_sec_info *) psecinfo;
788
753731ee 789 if (offset >= sec->_raw_size)
f5fa8ca2 790 {
753731ee 791 if (offset > sec->_raw_size)
923f08ff
AM
792 {
793 (*_bfd_error_handler)
753731ee
AM
794 (_("%s: access beyond end of merged section (%ld)"),
795 bfd_get_filename (sec->owner), (long) offset);
923f08ff 796 }
57ceae94 797 return (secinfo->first_str ? sec->_cooked_size : 0);
f5fa8ca2
JJ
798 }
799
800 if (secinfo->htab->strings)
801 {
802 if (sec->entsize == 1)
803 {
753731ee 804 p = secinfo->contents + offset - 1;
894bb1ee 805 while (p >= secinfo->contents && *p)
f5fa8ca2
JJ
806 --p;
807 ++p;
808 }
809 else
810 {
753731ee 811 p = secinfo->contents + (offset / sec->entsize) * sec->entsize;
f5fa8ca2
JJ
812 p -= sec->entsize;
813 while (p >= secinfo->contents)
814 {
815 unsigned int i;
816
817 for (i = 0; i < sec->entsize; ++i)
818 if (p[i] != '\0')
819 break;
820 if (i == sec->entsize)
821 break;
822 p -= sec->entsize;
823 }
824 p += sec->entsize;
825 }
826 }
827 else
828 {
753731ee 829 p = secinfo->contents + (offset / sec->entsize) * sec->entsize;
f5fa8ca2 830 }
b34976b6 831 entry = sec_merge_hash_lookup (secinfo->htab, p, 0, FALSE);
f5fa8ca2
JJ
832 if (!entry)
833 {
834 if (! secinfo->htab->strings)
835 abort ();
836 /* This should only happen if somebody points into the padding
837 after a NUL character but before next entity. */
838 if (*p)
839 abort ();
840 if (! secinfo->htab->first)
841 abort ();
842 entry = secinfo->htab->first;
753731ee
AM
843 p = (secinfo->contents + (offset / sec->entsize + 1) * sec->entsize
844 - entry->len);
f5fa8ca2
JJ
845 }
846
8550eb6e
JJ
847 *psec = entry->secinfo->sec;
848 return entry->u.index + (secinfo->contents + offset - p);
f5fa8ca2 849}
This page took 0.304438 seconds and 4 git commands to generate.