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