xfail pr18223 test for tic6x
[deliverable/binutils-gdb.git] / bfd / merge.c
CommitLineData
f5fa8ca2 1/* SEC_MERGE support.
b90efa5b 2 Copyright (C) 2001-2015 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
cd123cb7 9 the Free Software Foundation; either version 3 of the License, or
7217313c 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
cd123cb7
NC
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
21
f5fa8ca2
JJ
22
23/* This file contains support for merging duplicate entities within sections,
24 as used in ELF SHF_MERGE. */
25
f5fa8ca2 26#include "sysdep.h"
3db64b00 27#include "bfd.h"
f5fa8ca2 28#include "libbfd.h"
8550eb6e 29#include "hashtab.h"
7217313c 30#include "libiberty.h"
f5fa8ca2 31
8550eb6e
JJ
32struct sec_merge_sec_info;
33
f5fa8ca2
JJ
34/* An entry in the section merge hash table. */
35
36struct sec_merge_hash_entry
37{
38 struct bfd_hash_entry root;
ddb2b442 39 /* Length of this entry. This includes the zero terminator. */
f5fa8ca2 40 unsigned int len;
a531bbd2
JJ
41 /* Start of this string needs to be aligned to
42 alignment octets (not 1 << align). */
43 unsigned int alignment;
7217313c
NC
44 union
45 {
8550eb6e
JJ
46 /* Index within the merged section. */
47 bfd_size_type index;
8550eb6e
JJ
48 /* Entry this is a suffix of (if alignment is 0). */
49 struct sec_merge_hash_entry *suffix;
50 } u;
f5fa8ca2 51 /* Which section is it in. */
8550eb6e 52 struct sec_merge_sec_info *secinfo;
f5fa8ca2
JJ
53 /* Next entity in the hash table. */
54 struct sec_merge_hash_entry *next;
55};
56
57/* The section merge hash table. */
58
59struct sec_merge_hash
60{
61 struct bfd_hash_table table;
62 /* Next available index. */
63 bfd_size_type size;
64 /* First entity in the SEC_MERGE sections of this type. */
65 struct sec_merge_hash_entry *first;
66 /* Last entity in the SEC_MERGE sections of this type. */
67 struct sec_merge_hash_entry *last;
68 /* Entity size. */
69 unsigned int entsize;
f5fa8ca2 70 /* Are entries fixed size or zero terminated strings? */
b34976b6 71 bfd_boolean strings;
f5fa8ca2
JJ
72};
73
74struct sec_merge_info
75{
76 /* Chain of sec_merge_infos. */
77 struct sec_merge_info *next;
8550eb6e
JJ
78 /* Chain of sec_merge_sec_infos. */
79 struct sec_merge_sec_info *chain;
f5fa8ca2
JJ
80 /* A hash table used to hold section content. */
81 struct sec_merge_hash *htab;
f5fa8ca2
JJ
82};
83
84struct sec_merge_sec_info
85{
8550eb6e
JJ
86 /* Chain of sec_merge_sec_infos. */
87 struct sec_merge_sec_info *next;
88 /* The corresponding section. */
89 asection *sec;
90 /* Pointer to merge_info pointing to us. */
ac0e732e 91 void **psecinfo;
f5fa8ca2
JJ
92 /* A hash table used to hold section content. */
93 struct sec_merge_hash *htab;
94 /* First string in this section. */
57ceae94 95 struct sec_merge_hash_entry *first_str;
f5fa8ca2
JJ
96 /* Original section content. */
97 unsigned char contents[1];
98};
99
f5fa8ca2
JJ
100
101/* Routine to create an entry in a section merge hashtab. */
102
103static struct bfd_hash_entry *
ac0e732e
AJ
104sec_merge_hash_newfunc (struct bfd_hash_entry *entry,
105 struct bfd_hash_table *table, const char *string)
f5fa8ca2 106{
f5fa8ca2
JJ
107 /* Allocate the structure if it has not already been allocated by a
108 subclass. */
57ceae94 109 if (entry == NULL)
a50b1753
NC
110 entry = (struct bfd_hash_entry *)
111 bfd_hash_allocate (table, sizeof (struct sec_merge_hash_entry));
57ceae94 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 137{
91d6fa6a
NC
138 const unsigned char *s;
139 unsigned long hash;
140 unsigned int c;
f5fa8ca2
JJ
141 struct sec_merge_hash_entry *hashp;
142 unsigned int len, i;
91d6fa6a 143 unsigned int _index;
f5fa8ca2
JJ
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
91d6fa6a
NC
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 222 hashp = ((struct sec_merge_hash_entry *)
a69898aa 223 bfd_hash_insert (&table->table, string, hash));
57ceae94
AM
224 if (hashp == NULL)
225 return NULL;
f5fa8ca2 226 hashp->len = len;
a531bbd2 227 hashp->alignment = alignment;
f5fa8ca2
JJ
228 return hashp;
229}
230
231/* Create a new hash table. */
232
233static struct sec_merge_hash *
ac0e732e 234sec_merge_init (unsigned int entsize, bfd_boolean strings)
f5fa8ca2
JJ
235{
236 struct sec_merge_hash *table;
237
a50b1753 238 table = (struct sec_merge_hash *) bfd_malloc (sizeof (struct sec_merge_hash));
f5fa8ca2
JJ
239 if (table == NULL)
240 return NULL;
241
d05da6a8 242 if (! bfd_hash_table_init_n (&table->table, sec_merge_hash_newfunc,
66eb6687 243 sizeof (struct sec_merge_hash_entry), 16699))
f5fa8ca2
JJ
244 {
245 free (table);
246 return NULL;
247 }
248
249 table->size = 0;
250 table->first = NULL;
251 table->last = NULL;
f5fa8ca2
JJ
252 table->entsize = entsize;
253 table->strings = strings;
254
255 return table;
256}
257
258/* Get the index of an entity in a hash table, adding it if it is not
259 already present. */
260
261static struct sec_merge_hash_entry *
ac0e732e
AJ
262sec_merge_add (struct sec_merge_hash *tab, const char *str,
263 unsigned int alignment, struct sec_merge_sec_info *secinfo)
f5fa8ca2 264{
91d6fa6a 265 struct sec_merge_hash_entry *entry;
f5fa8ca2 266
9ca98086 267 entry = sec_merge_hash_lookup (tab, str, alignment, TRUE);
f5fa8ca2
JJ
268 if (entry == NULL)
269 return NULL;
270
8550eb6e 271 if (entry->secinfo == NULL)
f5fa8ca2 272 {
8550eb6e
JJ
273 tab->size++;
274 entry->secinfo = secinfo;
f5fa8ca2
JJ
275 if (tab->first == NULL)
276 tab->first = entry;
277 else
278 tab->last->next = entry;
279 tab->last = entry;
280 }
281
282 return entry;
283}
284
b34976b6 285static bfd_boolean
ddb2b442 286sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry)
f5fa8ca2 287{
8550eb6e
JJ
288 struct sec_merge_sec_info *secinfo = entry->secinfo;
289 asection *sec = secinfo->sec;
92ceba1e 290 char *pad = NULL;
a531bbd2 291 bfd_size_type off = 0;
57ceae94 292 int alignment_power = sec->output_section->alignment_power;
f5fa8ca2 293
a531bbd2 294 if (alignment_power)
92ceba1e 295 {
a50b1753 296 pad = (char *) bfd_zmalloc ((bfd_size_type) 1 << alignment_power);
92ceba1e
AM
297 if (pad == NULL)
298 return FALSE;
299 }
f5fa8ca2 300
8550eb6e 301 for (; entry != NULL && entry->secinfo == secinfo; entry = entry->next)
f5fa8ca2 302 {
92ceba1e
AM
303 const char *str;
304 bfd_size_type len;
f5fa8ca2 305
92ceba1e
AM
306 len = -off & (entry->alignment - 1);
307 if (len != 0)
a531bbd2 308 {
57ceae94 309 if (bfd_bwrite (pad, len, abfd) != len)
92ceba1e 310 goto err;
a531bbd2
JJ
311 off += len;
312 }
313
f5fa8ca2
JJ
314 str = entry->root.string;
315 len = entry->len;
316
57ceae94 317 if (bfd_bwrite (str, len, abfd) != len)
92ceba1e 318 goto err;
f5fa8ca2 319
a531bbd2 320 off += len;
f5fa8ca2
JJ
321 }
322
92ceba1e
AM
323 /* Trailing alignment needed? */
324 off = sec->size - off;
325 if (off != 0
326 && bfd_bwrite (pad, off, abfd) != off)
327 goto err;
328
329 if (pad != NULL)
f5fa8ca2 330 free (pad);
92ceba1e 331 return TRUE;
f5fa8ca2 332
92ceba1e
AM
333 err:
334 if (pad != NULL)
335 free (pad);
336 return FALSE;
f5fa8ca2
JJ
337}
338
57ceae94
AM
339/* Register a SEC_MERGE section as a candidate for merging.
340 This function is called for all non-dynamic SEC_MERGE input sections. */
f5fa8ca2 341
b34976b6 342bfd_boolean
57ceae94
AM
343_bfd_add_merge_section (bfd *abfd, void **psinfo, asection *sec,
344 void **psecinfo)
f5fa8ca2 345{
f5fa8ca2
JJ
346 struct sec_merge_info *sinfo;
347 struct sec_merge_sec_info *secinfo;
f5fa8ca2 348 unsigned int align;
dc810e39 349 bfd_size_type amt;
4a114e3e 350 bfd_byte *contents;
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. */
a50b1753
NC
394 sinfo = (struct sec_merge_info *)
395 bfd_alloc (abfd, sizeof (struct sec_merge_info));
f5fa8ca2
JJ
396 if (sinfo == NULL)
397 goto error_return;
398 sinfo->next = (struct sec_merge_info *) *psinfo;
8550eb6e 399 sinfo->chain = NULL;
ac0e732e 400 *psinfo = sinfo;
699cb9b8 401 sinfo->htab = sec_merge_init (sec->entsize, (sec->flags & SEC_STRINGS));
f5fa8ca2
JJ
402 if (sinfo->htab == NULL)
403 goto error_return;
404 }
405
406 /* Read the section from abfd. */
407
9ca98086
AM
408 amt = sizeof (struct sec_merge_sec_info) - 1 + sec->size;
409 if (sec->flags & SEC_STRINGS)
410 /* Some versions of gcc may emit a string without a zero terminator.
411 See http://gcc.gnu.org/ml/gcc-patches/2006-06/msg01004.html
412 Allocate space for an extra zero. */
413 amt += sec->entsize;
dc810e39 414 *psecinfo = bfd_alloc (abfd, amt);
f5fa8ca2
JJ
415 if (*psecinfo == NULL)
416 goto error_return;
417
57ceae94 418 secinfo = (struct sec_merge_sec_info *) *psecinfo;
8550eb6e
JJ
419 if (sinfo->chain)
420 {
421 secinfo->next = sinfo->chain->next;
422 sinfo->chain->next = secinfo;
423 }
424 else
425 secinfo->next = secinfo;
426 sinfo->chain = secinfo;
427 secinfo->sec = sec;
428 secinfo->psecinfo = psecinfo;
f5fa8ca2 429 secinfo->htab = sinfo->htab;
57ceae94 430 secinfo->first_str = NULL;
f5fa8ca2 431
eea6121a 432 sec->rawsize = sec->size;
9ca98086
AM
433 if (sec->flags & SEC_STRINGS)
434 memset (secinfo->contents + sec->size, 0, sec->entsize);
4a114e3e
L
435 contents = secinfo->contents;
436 if (! bfd_get_full_section_contents (sec->owner, sec, &contents))
f5fa8ca2
JJ
437 goto error_return;
438
b34976b6 439 return TRUE;
8550eb6e
JJ
440
441 error_return:
442 *psecinfo = NULL;
b34976b6 443 return FALSE;
8550eb6e
JJ
444}
445
8550eb6e 446/* Record one section into the hash table. */
b34976b6 447static bfd_boolean
9ca98086 448record_section (struct sec_merge_info *sinfo,
ac0e732e 449 struct sec_merge_sec_info *secinfo)
8550eb6e
JJ
450{
451 asection *sec = secinfo->sec;
452 struct sec_merge_hash_entry *entry;
b34976b6 453 bfd_boolean nul;
8550eb6e
JJ
454 unsigned char *p, *end;
455 bfd_vma mask, eltalign;
456 unsigned int align, i;
457
57ceae94 458 align = sec->alignment_power;
eea6121a 459 end = secinfo->contents + sec->size;
b34976b6 460 nul = FALSE;
dc810e39 461 mask = ((bfd_vma) 1 << align) - 1;
f5fa8ca2
JJ
462 if (sec->flags & SEC_STRINGS)
463 {
dc810e39 464 for (p = secinfo->contents; p < end; )
f5fa8ca2 465 {
a531bbd2
JJ
466 eltalign = p - secinfo->contents;
467 eltalign = ((eltalign ^ (eltalign - 1)) + 1) >> 1;
468 if (!eltalign || eltalign > mask)
469 eltalign = mask + 1;
f075ee0c
AM
470 entry = sec_merge_add (sinfo->htab, (char *) p, (unsigned) eltalign,
471 secinfo);
8550eb6e
JJ
472 if (! entry)
473 goto error_return;
f5fa8ca2
JJ
474 p += entry->len;
475 if (sec->entsize == 1)
476 {
477 while (p < end && *p == 0)
478 {
479 if (!nul && !((p - secinfo->contents) & mask))
480 {
b34976b6 481 nul = TRUE;
dc810e39
AM
482 entry = sec_merge_add (sinfo->htab, "",
483 (unsigned) mask + 1, secinfo);
8550eb6e
JJ
484 if (! entry)
485 goto error_return;
f5fa8ca2
JJ
486 }
487 p++;
ddb2b442 488 }
f5fa8ca2
JJ
489 }
490 else
491 {
492 while (p < end)
493 {
494 for (i = 0; i < sec->entsize; i++)
495 if (p[i] != '\0')
496 break;
497 if (i != sec->entsize)
498 break;
499 if (!nul && !((p - secinfo->contents) & mask))
500 {
b34976b6 501 nul = TRUE;
f075ee0c 502 entry = sec_merge_add (sinfo->htab, (char *) p,
dc810e39 503 (unsigned) mask + 1, secinfo);
8550eb6e
JJ
504 if (! entry)
505 goto error_return;
f5fa8ca2
JJ
506 }
507 p += sec->entsize;
508 }
509 }
510 }
511 }
512 else
513 {
514 for (p = secinfo->contents; p < end; p += sec->entsize)
515 {
f075ee0c 516 entry = sec_merge_add (sinfo->htab, (char *) p, 1, secinfo);
8550eb6e
JJ
517 if (! entry)
518 goto error_return;
519 }
520 }
521
b34976b6 522 return TRUE;
8550eb6e
JJ
523
524error_return:
525 for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
526 *secinfo->psecinfo = NULL;
b34976b6 527 return FALSE;
8550eb6e
JJ
528}
529
ddb2b442
AM
530static int
531strrevcmp (const void *a, const void *b)
532{
533 struct sec_merge_hash_entry *A = *(struct sec_merge_hash_entry **) a;
534 struct sec_merge_hash_entry *B = *(struct sec_merge_hash_entry **) b;
535 unsigned int lenA = A->len;
536 unsigned int lenB = B->len;
f075ee0c
AM
537 const unsigned char *s = (const unsigned char *) A->root.string + lenA - 1;
538 const unsigned char *t = (const unsigned char *) B->root.string + lenB - 1;
ddb2b442
AM
539 int l = lenA < lenB ? lenA : lenB;
540
541 while (l)
542 {
543 if (*s != *t)
544 return (int) *s - (int) *t;
545 s--;
546 t--;
547 l--;
548 }
549 return lenA - lenB;
550}
551
552/* Like strrevcmp, but for the case where all strings have the same
553 alignment > entsize. */
554
555static int
556strrevcmp_align (const void *a, const void *b)
557{
558 struct sec_merge_hash_entry *A = *(struct sec_merge_hash_entry **) a;
559 struct sec_merge_hash_entry *B = *(struct sec_merge_hash_entry **) b;
560 unsigned int lenA = A->len;
561 unsigned int lenB = B->len;
f075ee0c
AM
562 const unsigned char *s = (const unsigned char *) A->root.string + lenA - 1;
563 const unsigned char *t = (const unsigned char *) B->root.string + lenB - 1;
ddb2b442
AM
564 int l = lenA < lenB ? lenA : lenB;
565 int tail_align = (lenA & (A->alignment - 1)) - (lenB & (A->alignment - 1));
566
567 if (tail_align != 0)
568 return tail_align;
569
570 while (l)
571 {
572 if (*s != *t)
573 return (int) *s - (int) *t;
574 s--;
575 t--;
576 l--;
577 }
578 return lenA - lenB;
579}
580
581static inline int
582is_suffix (const struct sec_merge_hash_entry *A,
583 const struct sec_merge_hash_entry *B)
584{
585 if (A->len <= B->len)
586 /* B cannot be a suffix of A unless A is equal to B, which is guaranteed
587 not to be equal by the hash table. */
588 return 0;
589
590 return memcmp (A->root.string + (A->len - B->len),
591 B->root.string, B->len) == 0;
592}
593
8550eb6e
JJ
594/* This is a helper function for _bfd_merge_sections. It attempts to
595 merge strings matching suffixes of longer strings. */
596static void
ac0e732e 597merge_strings (struct sec_merge_info *sinfo)
8550eb6e 598{
ddb2b442 599 struct sec_merge_hash_entry **array, **a, *e;
8550eb6e 600 struct sec_merge_sec_info *secinfo;
dc810e39 601 bfd_size_type size, amt;
ddb2b442 602 unsigned int alignment = 0;
8550eb6e 603
ddb2b442 604 /* Now sort the strings */
dc810e39 605 amt = sinfo->htab->size * sizeof (struct sec_merge_hash_entry *);
a50b1753 606 array = (struct sec_merge_hash_entry **) bfd_malloc (amt);
8550eb6e
JJ
607 if (array == NULL)
608 goto alloc_failure;
609
610 for (e = sinfo->htab->first, a = array; e; e = e->next)
611 if (e->alignment)
ddb2b442
AM
612 {
613 *a++ = e;
614 /* Adjust the length to not include the zero terminator. */
615 e->len -= sinfo->htab->entsize;
616 if (alignment != e->alignment)
617 {
618 if (alignment == 0)
619 alignment = e->alignment;
620 else
621 alignment = (unsigned) -1;
622 }
623 }
8550eb6e
JJ
624
625 sinfo->htab->size = a - array;
ddb2b442 626 if (sinfo->htab->size != 0)
8550eb6e 627 {
ddb2b442
AM
628 qsort (array, (size_t) sinfo->htab->size,
629 sizeof (struct sec_merge_hash_entry *),
630 (alignment != (unsigned) -1 && alignment > sinfo->htab->entsize
631 ? strrevcmp_align : strrevcmp));
632
633 /* Loop over the sorted array and merge suffixes */
634 e = *--a;
635 e->len += sinfo->htab->entsize;
636 while (--a >= array)
8550eb6e 637 {
ddb2b442 638 struct sec_merge_hash_entry *cmp = *a;
8550eb6e 639
ddb2b442
AM
640 cmp->len += sinfo->htab->entsize;
641 if (e->alignment >= cmp->alignment
642 && !((e->len - cmp->len) & (cmp->alignment - 1))
643 && is_suffix (e, cmp))
644 {
645 cmp->u.suffix = e;
646 cmp->alignment = 0;
f5fa8ca2 647 }
8550eb6e 648 else
ddb2b442 649 e = cmp;
8550eb6e 650 }
f5fa8ca2
JJ
651 }
652
8550eb6e
JJ
653alloc_failure:
654 if (array)
655 free (array);
8550eb6e
JJ
656
657 /* Now assign positions to the strings we want to keep. */
658 size = 0;
659 secinfo = sinfo->htab->first->secinfo;
660 for (e = sinfo->htab->first; e; e = e->next)
661 {
662 if (e->secinfo != secinfo)
663 {
eea6121a 664 secinfo->sec->size = size;
8550eb6e
JJ
665 secinfo = e->secinfo;
666 }
667 if (e->alignment)
668 {
57ceae94 669 if (e->secinfo->first_str == NULL)
8550eb6e 670 {
57ceae94 671 e->secinfo->first_str = e;
8550eb6e
JJ
672 size = 0;
673 }
674 size = (size + e->alignment - 1) & ~((bfd_vma) e->alignment - 1);
675 e->u.index = size;
676 size += e->len;
677 }
678 }
eea6121a 679 secinfo->sec->size = size;
8699aa54
AM
680 if (secinfo->sec->alignment_power != 0)
681 {
682 bfd_size_type align = (bfd_size_type) 1 << secinfo->sec->alignment_power;
683 secinfo->sec->size = (secinfo->sec->size + align - 1) & -align;
684 }
8550eb6e
JJ
685
686 /* And now adjust the rest, removing them from the chain (but not hashtable)
687 at the same time. */
688 for (a = &sinfo->htab->first, e = *a; e; e = e->next)
689 if (e->alignment)
690 a = &e->next;
691 else
692 {
693 *a = e->next;
694 if (e->len)
695 {
696 e->secinfo = e->u.suffix->secinfo;
697 e->alignment = e->u.suffix->alignment;
698 e->u.index = e->u.suffix->u.index + (e->u.suffix->len - e->len);
699 }
700 }
701}
f5fa8ca2 702
8550eb6e
JJ
703/* This function is called once after all SEC_MERGE sections are registered
704 with _bfd_merge_section. */
705
b34976b6 706bfd_boolean
e6c6c8f3 707_bfd_merge_sections (bfd *abfd,
8423293d
AM
708 struct bfd_link_info *info ATTRIBUTE_UNUSED,
709 void *xsinfo,
710 void (*remove_hook) (bfd *, asection *))
8550eb6e
JJ
711{
712 struct sec_merge_info *sinfo;
713
714 for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next)
715 {
716 struct sec_merge_sec_info * secinfo;
717
718 if (! sinfo->chain)
719 continue;
720
721 /* Move sinfo->chain to head of the chain, terminate it. */
722 secinfo = sinfo->chain;
723 sinfo->chain = secinfo->next;
724 secinfo->next = NULL;
725
726 /* Record the sections into the hash table. */
727 for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
728 if (secinfo->sec->flags & SEC_EXCLUDE)
d3c456e9
JJ
729 {
730 *secinfo->psecinfo = NULL;
731 if (remove_hook)
732 (*remove_hook) (abfd, secinfo->sec);
733 }
9ca98086 734 else if (! record_section (sinfo, secinfo))
8550eb6e
JJ
735 break;
736
737 if (secinfo)
738 continue;
739
86eaf01e
JJ
740 if (sinfo->htab->first == NULL)
741 continue;
742
8550eb6e
JJ
743 if (sinfo->htab->strings)
744 merge_strings (sinfo);
745 else
746 {
747 struct sec_merge_hash_entry *e;
748 bfd_size_type size = 0;
749
750 /* Things are much simpler for non-strings.
751 Just assign them slots in the section. */
752 secinfo = NULL;
753 for (e = sinfo->htab->first; e; e = e->next)
754 {
57ceae94 755 if (e->secinfo->first_str == NULL)
8550eb6e
JJ
756 {
757 if (secinfo)
eea6121a 758 secinfo->sec->size = size;
57ceae94 759 e->secinfo->first_str = e;
8550eb6e
JJ
760 size = 0;
761 }
762 size = (size + e->alignment - 1)
763 & ~((bfd_vma) e->alignment - 1);
764 e->u.index = size;
765 size += e->len;
766 secinfo = e->secinfo;
767 }
eea6121a 768 secinfo->sec->size = size;
8550eb6e
JJ
769 }
770
27c630ba 771 /* Finally remove all input sections which have not made it into
8550eb6e
JJ
772 the hash table at all. */
773 for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
57ceae94 774 if (secinfo->first_str == NULL)
a14a5de3 775 secinfo->sec->flags |= SEC_EXCLUDE | SEC_KEEP;
8550eb6e
JJ
776 }
777
b34976b6 778 return TRUE;
f5fa8ca2
JJ
779}
780
781/* Write out the merged section. */
782
b34976b6 783bfd_boolean
ac0e732e 784_bfd_write_merged_section (bfd *output_bfd, asection *sec, void *psecinfo)
f5fa8ca2
JJ
785{
786 struct sec_merge_sec_info *secinfo;
dc810e39 787 file_ptr pos;
f5fa8ca2
JJ
788
789 secinfo = (struct sec_merge_sec_info *) psecinfo;
790
e6c6c8f3
JM
791 if (!secinfo)
792 return FALSE;
793
57ceae94 794 if (secinfo->first_str == NULL)
b34976b6 795 return TRUE;
f5fa8ca2 796
5dabe785 797 /* FIXME: octets_per_byte. */
dc810e39
AM
798 pos = sec->output_section->filepos + sec->output_offset;
799 if (bfd_seek (output_bfd, pos, SEEK_SET) != 0)
b34976b6 800 return FALSE;
f5fa8ca2 801
57ceae94 802 if (! sec_merge_emit (output_bfd, secinfo->first_str))
b34976b6 803 return FALSE;
f5fa8ca2 804
b34976b6 805 return TRUE;
f5fa8ca2
JJ
806}
807
808/* Adjust an address in the SEC_MERGE section. Given OFFSET within
809 *PSEC, this returns the new offset in the adjusted SEC_MERGE
810 section and writes the new section back into *PSEC. */
811
812bfd_vma
ac0e732e 813_bfd_merged_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED, asection **psec,
753731ee 814 void *psecinfo, bfd_vma offset)
f5fa8ca2
JJ
815{
816 struct sec_merge_sec_info *secinfo;
817 struct sec_merge_hash_entry *entry;
818 unsigned char *p;
819 asection *sec = *psec;
820
821 secinfo = (struct sec_merge_sec_info *) psecinfo;
822
e6c6c8f3 823 if (!secinfo)
9ca98086 824 return offset;
e6c6c8f3 825
eea6121a 826 if (offset >= sec->rawsize)
f5fa8ca2 827 {
eea6121a 828 if (offset > sec->rawsize)
923f08ff
AM
829 {
830 (*_bfd_error_handler)
753731ee
AM
831 (_("%s: access beyond end of merged section (%ld)"),
832 bfd_get_filename (sec->owner), (long) offset);
923f08ff 833 }
eea6121a 834 return secinfo->first_str ? sec->size : 0;
f5fa8ca2
JJ
835 }
836
837 if (secinfo->htab->strings)
838 {
839 if (sec->entsize == 1)
840 {
753731ee 841 p = secinfo->contents + offset - 1;
894bb1ee 842 while (p >= secinfo->contents && *p)
f5fa8ca2
JJ
843 --p;
844 ++p;
845 }
846 else
847 {
753731ee 848 p = secinfo->contents + (offset / sec->entsize) * sec->entsize;
f5fa8ca2
JJ
849 p -= sec->entsize;
850 while (p >= secinfo->contents)
851 {
852 unsigned int i;
853
854 for (i = 0; i < sec->entsize; ++i)
855 if (p[i] != '\0')
856 break;
857 if (i == sec->entsize)
858 break;
859 p -= sec->entsize;
860 }
861 p += sec->entsize;
862 }
863 }
864 else
865 {
753731ee 866 p = secinfo->contents + (offset / sec->entsize) * sec->entsize;
f5fa8ca2 867 }
9ca98086 868 entry = sec_merge_hash_lookup (secinfo->htab, (char *) p, 0, FALSE);
f5fa8ca2
JJ
869 if (!entry)
870 {
871 if (! secinfo->htab->strings)
872 abort ();
873 /* This should only happen if somebody points into the padding
874 after a NUL character but before next entity. */
875 if (*p)
876 abort ();
877 if (! secinfo->htab->first)
878 abort ();
879 entry = secinfo->htab->first;
753731ee
AM
880 p = (secinfo->contents + (offset / sec->entsize + 1) * sec->entsize
881 - entry->len);
f5fa8ca2
JJ
882 }
883
8550eb6e
JJ
884 *psec = entry->secinfo->sec;
885 return entry->u.index + (secinfo->contents + offset - p);
f5fa8ca2 886}
9f7c3e5e
AM
887
888/* Tidy up when done. */
889
890void
891_bfd_merge_sections_free (void *xsinfo)
892{
893 struct sec_merge_info *sinfo;
894
895 for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next)
896 {
897 bfd_hash_table_free (&sinfo->htab->table);
898 free (sinfo->htab);
899 }
900}
This page took 0.849756 seconds and 4 git commands to generate.