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