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