]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - bfd/merge.c
Include <array> to declare std::array<>.
[thirdparty/binutils-gdb.git] / bfd / merge.c
CommitLineData
f5fa8ca2 1/* SEC_MERGE support.
2571583a 2 Copyright (C) 2001-2017 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"
0ce398f1 28#include "elf-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 110 if (entry == NULL)
a50b1753
NC
111 entry = (struct bfd_hash_entry *)
112 bfd_hash_allocate (table, sizeof (struct sec_merge_hash_entry));
57ceae94 113 if (entry == NULL)
f5fa8ca2
JJ
114 return NULL;
115
116 /* Call the allocation method of the superclass. */
57ceae94 117 entry = bfd_hash_newfunc (entry, table, string);
f5fa8ca2 118
57ceae94 119 if (entry != NULL)
f5fa8ca2
JJ
120 {
121 /* Initialize the local fields. */
57ceae94
AM
122 struct sec_merge_hash_entry *ret = (struct sec_merge_hash_entry *) entry;
123
8550eb6e 124 ret->u.suffix = NULL;
a531bbd2 125 ret->alignment = 0;
8550eb6e 126 ret->secinfo = NULL;
f5fa8ca2
JJ
127 ret->next = NULL;
128 }
129
57ceae94 130 return entry;
f5fa8ca2
JJ
131}
132
133/* Look up an entry in a section merge hash table. */
134
135static struct sec_merge_hash_entry *
ac0e732e
AJ
136sec_merge_hash_lookup (struct sec_merge_hash *table, const char *string,
137 unsigned int alignment, bfd_boolean create)
f5fa8ca2 138{
91d6fa6a
NC
139 const unsigned char *s;
140 unsigned long hash;
141 unsigned int c;
f5fa8ca2
JJ
142 struct sec_merge_hash_entry *hashp;
143 unsigned int len, i;
91d6fa6a 144 unsigned int _index;
f5fa8ca2
JJ
145
146 hash = 0;
147 len = 0;
148 s = (const unsigned char *) string;
149 if (table->strings)
150 {
151 if (table->entsize == 1)
152 {
153 while ((c = *s++) != '\0')
154 {
155 hash += c + (c << 17);
156 hash ^= hash >> 2;
157 ++len;
158 }
159 hash += len + (len << 17);
160 }
161 else
162 {
163 for (;;)
164 {
165 for (i = 0; i < table->entsize; ++i)
166 if (s[i] != '\0')
167 break;
168 if (i == table->entsize)
169 break;
170 for (i = 0; i < table->entsize; ++i)
171 {
172 c = *s++;
173 hash += c + (c << 17);
174 hash ^= hash >> 2;
175 }
176 ++len;
177 }
178 hash += len + (len << 17);
179 len *= table->entsize;
180 }
181 hash ^= hash >> 2;
182 len += table->entsize;
dc810e39 183 }
f5fa8ca2
JJ
184 else
185 {
186 for (i = 0; i < table->entsize; ++i)
187 {
188 c = *s++;
189 hash += c + (c << 17);
190 hash ^= hash >> 2;
191 }
192 len = table->entsize;
193 }
194
91d6fa6a
NC
195 _index = hash % table->table.size;
196 for (hashp = (struct sec_merge_hash_entry *) table->table.table[_index];
57ceae94 197 hashp != NULL;
a531bbd2 198 hashp = (struct sec_merge_hash_entry *) hashp->root.next)
f5fa8ca2
JJ
199 {
200 if (hashp->root.hash == hash
201 && len == hashp->len
202 && memcmp (hashp->root.string, string, len) == 0)
a531bbd2
JJ
203 {
204 /* If the string we found does not have at least the required
8550eb6e 205 alignment, we need to insert another copy. */
a531bbd2 206 if (hashp->alignment < alignment)
8550eb6e 207 {
ddb2b442
AM
208 if (create)
209 {
210 /* Mark the less aligned copy as deleted. */
211 hashp->len = 0;
212 hashp->alignment = 0;
213 }
8550eb6e
JJ
214 break;
215 }
a531bbd2
JJ
216 return hashp;
217 }
f5fa8ca2
JJ
218 }
219
220 if (! create)
57ceae94 221 return NULL;
f5fa8ca2 222
57ceae94 223 hashp = ((struct sec_merge_hash_entry *)
a69898aa 224 bfd_hash_insert (&table->table, string, hash));
57ceae94
AM
225 if (hashp == NULL)
226 return NULL;
f5fa8ca2 227 hashp->len = len;
a531bbd2 228 hashp->alignment = alignment;
f5fa8ca2
JJ
229 return hashp;
230}
231
232/* Create a new hash table. */
233
234static struct sec_merge_hash *
ac0e732e 235sec_merge_init (unsigned int entsize, bfd_boolean strings)
f5fa8ca2
JJ
236{
237 struct sec_merge_hash *table;
238
a50b1753 239 table = (struct sec_merge_hash *) bfd_malloc (sizeof (struct sec_merge_hash));
f5fa8ca2
JJ
240 if (table == NULL)
241 return NULL;
242
d05da6a8 243 if (! bfd_hash_table_init_n (&table->table, sec_merge_hash_newfunc,
66eb6687 244 sizeof (struct sec_merge_hash_entry), 16699))
f5fa8ca2
JJ
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 265{
91d6fa6a 266 struct sec_merge_hash_entry *entry;
f5fa8ca2 267
9ca98086 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
0ce398f1
L
287sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry,
288 unsigned char *contents, file_ptr offset)
f5fa8ca2 289{
8550eb6e
JJ
290 struct sec_merge_sec_info *secinfo = entry->secinfo;
291 asection *sec = secinfo->sec;
92ceba1e 292 char *pad = NULL;
a531bbd2 293 bfd_size_type off = 0;
57ceae94 294 int alignment_power = sec->output_section->alignment_power;
f5fa8ca2 295
a531bbd2 296 if (alignment_power)
92ceba1e 297 {
a50b1753 298 pad = (char *) bfd_zmalloc ((bfd_size_type) 1 << alignment_power);
92ceba1e
AM
299 if (pad == NULL)
300 return FALSE;
301 }
f5fa8ca2 302
8550eb6e 303 for (; entry != NULL && entry->secinfo == secinfo; entry = entry->next)
f5fa8ca2 304 {
92ceba1e
AM
305 const char *str;
306 bfd_size_type len;
f5fa8ca2 307
92ceba1e
AM
308 len = -off & (entry->alignment - 1);
309 if (len != 0)
a531bbd2 310 {
0ce398f1
L
311 if (contents)
312 {
313 memcpy (contents + offset, pad, len);
314 offset += len;
315 }
316 else if (bfd_bwrite (pad, len, abfd) != len)
92ceba1e 317 goto err;
a531bbd2
JJ
318 off += len;
319 }
320
f5fa8ca2
JJ
321 str = entry->root.string;
322 len = entry->len;
323
0ce398f1
L
324 if (contents)
325 {
326 memcpy (contents + offset, str, len);
327 offset += len;
328 }
329 else if (bfd_bwrite (str, len, abfd) != len)
92ceba1e 330 goto err;
f5fa8ca2 331
a531bbd2 332 off += len;
f5fa8ca2
JJ
333 }
334
92ceba1e
AM
335 /* Trailing alignment needed? */
336 off = sec->size - off;
0ce398f1
L
337 if (off != 0)
338 {
339 if (contents)
340 memcpy (contents + offset, pad, off);
341 else if (bfd_bwrite (pad, off, abfd) != off)
342 goto err;
343 }
92ceba1e
AM
344
345 if (pad != NULL)
f5fa8ca2 346 free (pad);
92ceba1e 347 return TRUE;
f5fa8ca2 348
92ceba1e
AM
349 err:
350 if (pad != NULL)
351 free (pad);
352 return FALSE;
f5fa8ca2
JJ
353}
354
57ceae94
AM
355/* Register a SEC_MERGE section as a candidate for merging.
356 This function is called for all non-dynamic SEC_MERGE input sections. */
f5fa8ca2 357
b34976b6 358bfd_boolean
57ceae94
AM
359_bfd_add_merge_section (bfd *abfd, void **psinfo, asection *sec,
360 void **psecinfo)
f5fa8ca2 361{
f5fa8ca2
JJ
362 struct sec_merge_info *sinfo;
363 struct sec_merge_sec_info *secinfo;
f5fa8ca2 364 unsigned int align;
dc810e39 365 bfd_size_type amt;
4a114e3e 366 bfd_byte *contents;
f5fa8ca2 367
57ceae94
AM
368 if ((abfd->flags & DYNAMIC) != 0
369 || (sec->flags & SEC_MERGE) == 0)
370 abort ();
371
eea6121a 372 if (sec->size == 0
57ceae94 373 || (sec->flags & SEC_EXCLUDE) != 0
f5fa8ca2 374 || sec->entsize == 0)
b34976b6 375 return TRUE;
f5fa8ca2
JJ
376
377 if ((sec->flags & SEC_RELOC) != 0)
378 {
379 /* We aren't prepared to handle relocations in merged sections. */
b34976b6 380 return TRUE;
f5fa8ca2
JJ
381 }
382
57ceae94
AM
383 align = sec->alignment_power;
384 if ((sec->entsize < (unsigned) 1 << align
a531bbd2
JJ
385 && ((sec->entsize & (sec->entsize - 1))
386 || !(sec->flags & SEC_STRINGS)))
57ceae94
AM
387 || (sec->entsize > (unsigned) 1 << align
388 && (sec->entsize & (((unsigned) 1 << align) - 1))))
f5fa8ca2
JJ
389 {
390 /* Sanity check. If string character size is smaller than
391 alignment, then we require character size to be a power
392 of 2, otherwise character size must be integer multiple
a531bbd2
JJ
393 of alignment. For non-string constants, alignment must
394 be smaller than or equal to entity size and entity size
395 must be integer multiple of alignment. */
b34976b6 396 return TRUE;
f5fa8ca2
JJ
397 }
398
f5fa8ca2 399 for (sinfo = (struct sec_merge_info *) *psinfo; sinfo; sinfo = sinfo->next)
8550eb6e
JJ
400 if ((secinfo = sinfo->chain)
401 && ! ((secinfo->sec->flags ^ sec->flags) & (SEC_MERGE | SEC_STRINGS))
402 && secinfo->sec->entsize == sec->entsize
57ceae94
AM
403 && secinfo->sec->alignment_power == sec->alignment_power
404 && secinfo->sec->output_section == sec->output_section)
f5fa8ca2
JJ
405 break;
406
407 if (sinfo == NULL)
408 {
409 /* Initialize the information we need to keep track of. */
a50b1753
NC
410 sinfo = (struct sec_merge_info *)
411 bfd_alloc (abfd, sizeof (struct sec_merge_info));
f5fa8ca2
JJ
412 if (sinfo == NULL)
413 goto error_return;
414 sinfo->next = (struct sec_merge_info *) *psinfo;
8550eb6e 415 sinfo->chain = NULL;
ac0e732e 416 *psinfo = sinfo;
699cb9b8 417 sinfo->htab = sec_merge_init (sec->entsize, (sec->flags & SEC_STRINGS));
f5fa8ca2
JJ
418 if (sinfo->htab == NULL)
419 goto error_return;
420 }
421
422 /* Read the section from abfd. */
423
9ca98086
AM
424 amt = sizeof (struct sec_merge_sec_info) - 1 + sec->size;
425 if (sec->flags & SEC_STRINGS)
426 /* Some versions of gcc may emit a string without a zero terminator.
427 See http://gcc.gnu.org/ml/gcc-patches/2006-06/msg01004.html
428 Allocate space for an extra zero. */
429 amt += sec->entsize;
dc810e39 430 *psecinfo = bfd_alloc (abfd, amt);
f5fa8ca2
JJ
431 if (*psecinfo == NULL)
432 goto error_return;
433
57ceae94 434 secinfo = (struct sec_merge_sec_info *) *psecinfo;
8550eb6e
JJ
435 if (sinfo->chain)
436 {
437 secinfo->next = sinfo->chain->next;
438 sinfo->chain->next = secinfo;
439 }
440 else
441 secinfo->next = secinfo;
442 sinfo->chain = secinfo;
443 secinfo->sec = sec;
444 secinfo->psecinfo = psecinfo;
f5fa8ca2 445 secinfo->htab = sinfo->htab;
57ceae94 446 secinfo->first_str = NULL;
f5fa8ca2 447
eea6121a 448 sec->rawsize = sec->size;
9ca98086
AM
449 if (sec->flags & SEC_STRINGS)
450 memset (secinfo->contents + sec->size, 0, sec->entsize);
4a114e3e
L
451 contents = secinfo->contents;
452 if (! bfd_get_full_section_contents (sec->owner, sec, &contents))
f5fa8ca2
JJ
453 goto error_return;
454
b34976b6 455 return TRUE;
8550eb6e
JJ
456
457 error_return:
458 *psecinfo = NULL;
b34976b6 459 return FALSE;
8550eb6e
JJ
460}
461
8550eb6e 462/* Record one section into the hash table. */
b34976b6 463static bfd_boolean
9ca98086 464record_section (struct sec_merge_info *sinfo,
ac0e732e 465 struct sec_merge_sec_info *secinfo)
8550eb6e
JJ
466{
467 asection *sec = secinfo->sec;
468 struct sec_merge_hash_entry *entry;
b34976b6 469 bfd_boolean nul;
8550eb6e
JJ
470 unsigned char *p, *end;
471 bfd_vma mask, eltalign;
472 unsigned int align, i;
473
57ceae94 474 align = sec->alignment_power;
eea6121a 475 end = secinfo->contents + sec->size;
b34976b6 476 nul = FALSE;
dc810e39 477 mask = ((bfd_vma) 1 << align) - 1;
f5fa8ca2
JJ
478 if (sec->flags & SEC_STRINGS)
479 {
dc810e39 480 for (p = secinfo->contents; p < end; )
f5fa8ca2 481 {
a531bbd2
JJ
482 eltalign = p - secinfo->contents;
483 eltalign = ((eltalign ^ (eltalign - 1)) + 1) >> 1;
484 if (!eltalign || eltalign > mask)
485 eltalign = mask + 1;
f075ee0c
AM
486 entry = sec_merge_add (sinfo->htab, (char *) p, (unsigned) eltalign,
487 secinfo);
8550eb6e
JJ
488 if (! entry)
489 goto error_return;
f5fa8ca2
JJ
490 p += entry->len;
491 if (sec->entsize == 1)
492 {
493 while (p < end && *p == 0)
494 {
495 if (!nul && !((p - secinfo->contents) & mask))
496 {
b34976b6 497 nul = TRUE;
dc810e39
AM
498 entry = sec_merge_add (sinfo->htab, "",
499 (unsigned) mask + 1, secinfo);
8550eb6e
JJ
500 if (! entry)
501 goto error_return;
f5fa8ca2
JJ
502 }
503 p++;
ddb2b442 504 }
f5fa8ca2
JJ
505 }
506 else
507 {
508 while (p < end)
509 {
510 for (i = 0; i < sec->entsize; i++)
511 if (p[i] != '\0')
512 break;
513 if (i != sec->entsize)
514 break;
515 if (!nul && !((p - secinfo->contents) & mask))
516 {
b34976b6 517 nul = TRUE;
f075ee0c 518 entry = sec_merge_add (sinfo->htab, (char *) p,
dc810e39 519 (unsigned) mask + 1, secinfo);
8550eb6e
JJ
520 if (! entry)
521 goto error_return;
f5fa8ca2
JJ
522 }
523 p += sec->entsize;
524 }
525 }
526 }
527 }
528 else
529 {
530 for (p = secinfo->contents; p < end; p += sec->entsize)
531 {
f075ee0c 532 entry = sec_merge_add (sinfo->htab, (char *) p, 1, secinfo);
8550eb6e
JJ
533 if (! entry)
534 goto error_return;
535 }
536 }
537
b34976b6 538 return TRUE;
8550eb6e
JJ
539
540error_return:
541 for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
542 *secinfo->psecinfo = NULL;
b34976b6 543 return FALSE;
8550eb6e
JJ
544}
545
ddb2b442
AM
546static int
547strrevcmp (const void *a, const void *b)
548{
549 struct sec_merge_hash_entry *A = *(struct sec_merge_hash_entry **) a;
550 struct sec_merge_hash_entry *B = *(struct sec_merge_hash_entry **) b;
551 unsigned int lenA = A->len;
552 unsigned int lenB = B->len;
f075ee0c
AM
553 const unsigned char *s = (const unsigned char *) A->root.string + lenA - 1;
554 const unsigned char *t = (const unsigned char *) B->root.string + lenB - 1;
ddb2b442
AM
555 int l = lenA < lenB ? lenA : lenB;
556
557 while (l)
558 {
559 if (*s != *t)
560 return (int) *s - (int) *t;
561 s--;
562 t--;
563 l--;
564 }
565 return lenA - lenB;
566}
567
568/* Like strrevcmp, but for the case where all strings have the same
569 alignment > entsize. */
570
571static int
572strrevcmp_align (const void *a, const void *b)
573{
574 struct sec_merge_hash_entry *A = *(struct sec_merge_hash_entry **) a;
575 struct sec_merge_hash_entry *B = *(struct sec_merge_hash_entry **) b;
576 unsigned int lenA = A->len;
577 unsigned int lenB = B->len;
f075ee0c
AM
578 const unsigned char *s = (const unsigned char *) A->root.string + lenA - 1;
579 const unsigned char *t = (const unsigned char *) B->root.string + lenB - 1;
ddb2b442
AM
580 int l = lenA < lenB ? lenA : lenB;
581 int tail_align = (lenA & (A->alignment - 1)) - (lenB & (A->alignment - 1));
582
583 if (tail_align != 0)
584 return tail_align;
585
586 while (l)
587 {
588 if (*s != *t)
589 return (int) *s - (int) *t;
590 s--;
591 t--;
592 l--;
593 }
594 return lenA - lenB;
595}
596
597static inline int
598is_suffix (const struct sec_merge_hash_entry *A,
599 const struct sec_merge_hash_entry *B)
600{
601 if (A->len <= B->len)
602 /* B cannot be a suffix of A unless A is equal to B, which is guaranteed
603 not to be equal by the hash table. */
604 return 0;
605
606 return memcmp (A->root.string + (A->len - B->len),
607 B->root.string, B->len) == 0;
608}
609
8550eb6e
JJ
610/* This is a helper function for _bfd_merge_sections. It attempts to
611 merge strings matching suffixes of longer strings. */
f6ac8c52 612static bfd_boolean
ac0e732e 613merge_strings (struct sec_merge_info *sinfo)
8550eb6e 614{
ddb2b442 615 struct sec_merge_hash_entry **array, **a, *e;
8550eb6e 616 struct sec_merge_sec_info *secinfo;
dc810e39 617 bfd_size_type size, amt;
ddb2b442 618 unsigned int alignment = 0;
8550eb6e 619
ddb2b442 620 /* Now sort the strings */
dc810e39 621 amt = sinfo->htab->size * sizeof (struct sec_merge_hash_entry *);
a50b1753 622 array = (struct sec_merge_hash_entry **) bfd_malloc (amt);
8550eb6e 623 if (array == NULL)
f6ac8c52 624 return FALSE;
8550eb6e
JJ
625
626 for (e = sinfo->htab->first, a = array; e; e = e->next)
627 if (e->alignment)
ddb2b442
AM
628 {
629 *a++ = e;
630 /* Adjust the length to not include the zero terminator. */
631 e->len -= sinfo->htab->entsize;
632 if (alignment != e->alignment)
633 {
634 if (alignment == 0)
635 alignment = e->alignment;
636 else
637 alignment = (unsigned) -1;
638 }
639 }
8550eb6e
JJ
640
641 sinfo->htab->size = a - array;
ddb2b442 642 if (sinfo->htab->size != 0)
8550eb6e 643 {
ddb2b442
AM
644 qsort (array, (size_t) sinfo->htab->size,
645 sizeof (struct sec_merge_hash_entry *),
646 (alignment != (unsigned) -1 && alignment > sinfo->htab->entsize
647 ? strrevcmp_align : strrevcmp));
648
649 /* Loop over the sorted array and merge suffixes */
650 e = *--a;
651 e->len += sinfo->htab->entsize;
652 while (--a >= array)
8550eb6e 653 {
ddb2b442 654 struct sec_merge_hash_entry *cmp = *a;
8550eb6e 655
ddb2b442
AM
656 cmp->len += sinfo->htab->entsize;
657 if (e->alignment >= cmp->alignment
658 && !((e->len - cmp->len) & (cmp->alignment - 1))
659 && is_suffix (e, cmp))
660 {
661 cmp->u.suffix = e;
662 cmp->alignment = 0;
f5fa8ca2 663 }
8550eb6e 664 else
ddb2b442 665 e = cmp;
8550eb6e 666 }
f5fa8ca2
JJ
667 }
668
f6ac8c52 669 free (array);
8550eb6e
JJ
670
671 /* Now assign positions to the strings we want to keep. */
672 size = 0;
673 secinfo = sinfo->htab->first->secinfo;
674 for (e = sinfo->htab->first; e; e = e->next)
675 {
676 if (e->secinfo != secinfo)
677 {
eea6121a 678 secinfo->sec->size = size;
8550eb6e
JJ
679 secinfo = e->secinfo;
680 }
681 if (e->alignment)
682 {
57ceae94 683 if (e->secinfo->first_str == NULL)
8550eb6e 684 {
57ceae94 685 e->secinfo->first_str = e;
8550eb6e
JJ
686 size = 0;
687 }
688 size = (size + e->alignment - 1) & ~((bfd_vma) e->alignment - 1);
689 e->u.index = size;
690 size += e->len;
691 }
692 }
eea6121a 693 secinfo->sec->size = size;
8699aa54
AM
694 if (secinfo->sec->alignment_power != 0)
695 {
696 bfd_size_type align = (bfd_size_type) 1 << secinfo->sec->alignment_power;
697 secinfo->sec->size = (secinfo->sec->size + align - 1) & -align;
698 }
8550eb6e
JJ
699
700 /* And now adjust the rest, removing them from the chain (but not hashtable)
701 at the same time. */
702 for (a = &sinfo->htab->first, e = *a; e; e = e->next)
703 if (e->alignment)
704 a = &e->next;
705 else
706 {
707 *a = e->next;
708 if (e->len)
709 {
710 e->secinfo = e->u.suffix->secinfo;
711 e->alignment = e->u.suffix->alignment;
712 e->u.index = e->u.suffix->u.index + (e->u.suffix->len - e->len);
713 }
714 }
f6ac8c52 715 return TRUE;
8550eb6e 716}
f5fa8ca2 717
8550eb6e
JJ
718/* This function is called once after all SEC_MERGE sections are registered
719 with _bfd_merge_section. */
720
b34976b6 721bfd_boolean
e6c6c8f3 722_bfd_merge_sections (bfd *abfd,
8423293d
AM
723 struct bfd_link_info *info ATTRIBUTE_UNUSED,
724 void *xsinfo,
725 void (*remove_hook) (bfd *, asection *))
8550eb6e
JJ
726{
727 struct sec_merge_info *sinfo;
728
729 for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next)
730 {
731 struct sec_merge_sec_info * secinfo;
732
733 if (! sinfo->chain)
734 continue;
735
736 /* Move sinfo->chain to head of the chain, terminate it. */
737 secinfo = sinfo->chain;
738 sinfo->chain = secinfo->next;
739 secinfo->next = NULL;
740
741 /* Record the sections into the hash table. */
742 for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
743 if (secinfo->sec->flags & SEC_EXCLUDE)
d3c456e9
JJ
744 {
745 *secinfo->psecinfo = NULL;
746 if (remove_hook)
747 (*remove_hook) (abfd, secinfo->sec);
748 }
9ca98086 749 else if (! record_section (sinfo, secinfo))
f6ac8c52 750 return FALSE;
8550eb6e
JJ
751
752 if (secinfo)
753 continue;
754
86eaf01e
JJ
755 if (sinfo->htab->first == NULL)
756 continue;
757
8550eb6e 758 if (sinfo->htab->strings)
f6ac8c52
AM
759 {
760 if (!merge_strings (sinfo))
761 return FALSE;
762 }
8550eb6e
JJ
763 else
764 {
765 struct sec_merge_hash_entry *e;
766 bfd_size_type size = 0;
767
768 /* Things are much simpler for non-strings.
769 Just assign them slots in the section. */
770 secinfo = NULL;
771 for (e = sinfo->htab->first; e; e = e->next)
772 {
57ceae94 773 if (e->secinfo->first_str == NULL)
8550eb6e
JJ
774 {
775 if (secinfo)
eea6121a 776 secinfo->sec->size = size;
57ceae94 777 e->secinfo->first_str = e;
8550eb6e
JJ
778 size = 0;
779 }
780 size = (size + e->alignment - 1)
781 & ~((bfd_vma) e->alignment - 1);
782 e->u.index = size;
783 size += e->len;
784 secinfo = e->secinfo;
785 }
eea6121a 786 secinfo->sec->size = size;
8550eb6e
JJ
787 }
788
27c630ba 789 /* Finally remove all input sections which have not made it into
8550eb6e
JJ
790 the hash table at all. */
791 for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
57ceae94 792 if (secinfo->first_str == NULL)
a14a5de3 793 secinfo->sec->flags |= SEC_EXCLUDE | SEC_KEEP;
8550eb6e
JJ
794 }
795
b34976b6 796 return TRUE;
f5fa8ca2
JJ
797}
798
799/* Write out the merged section. */
800
b34976b6 801bfd_boolean
ac0e732e 802_bfd_write_merged_section (bfd *output_bfd, asection *sec, void *psecinfo)
f5fa8ca2
JJ
803{
804 struct sec_merge_sec_info *secinfo;
dc810e39 805 file_ptr pos;
0ce398f1
L
806 unsigned char *contents;
807 Elf_Internal_Shdr *hdr;
f5fa8ca2
JJ
808
809 secinfo = (struct sec_merge_sec_info *) psecinfo;
810
e6c6c8f3
JM
811 if (!secinfo)
812 return FALSE;
813
57ceae94 814 if (secinfo->first_str == NULL)
b34976b6 815 return TRUE;
f5fa8ca2 816
5dabe785 817 /* FIXME: octets_per_byte. */
0ce398f1
L
818 hdr = &elf_section_data (sec->output_section)->this_hdr;
819 if (hdr->sh_offset == (file_ptr) -1)
820 {
821 /* We must compress this section. Write output to the
822 buffer. */
823 contents = hdr->contents;
824 if ((sec->output_section->flags & SEC_ELF_COMPRESS) == 0
825 || contents == NULL)
826 abort ();
827 }
828 else
829 {
830 contents = NULL;
831 pos = sec->output_section->filepos + sec->output_offset;
832 if (bfd_seek (output_bfd, pos, SEEK_SET) != 0)
833 return FALSE;
834 }
f5fa8ca2 835
0ce398f1
L
836 if (! sec_merge_emit (output_bfd, secinfo->first_str, contents,
837 sec->output_offset))
b34976b6 838 return FALSE;
f5fa8ca2 839
b34976b6 840 return TRUE;
f5fa8ca2
JJ
841}
842
843/* Adjust an address in the SEC_MERGE section. Given OFFSET within
844 *PSEC, this returns the new offset in the adjusted SEC_MERGE
845 section and writes the new section back into *PSEC. */
846
847bfd_vma
ac0e732e 848_bfd_merged_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED, asection **psec,
753731ee 849 void *psecinfo, bfd_vma offset)
f5fa8ca2
JJ
850{
851 struct sec_merge_sec_info *secinfo;
852 struct sec_merge_hash_entry *entry;
853 unsigned char *p;
854 asection *sec = *psec;
855
856 secinfo = (struct sec_merge_sec_info *) psecinfo;
857
e6c6c8f3 858 if (!secinfo)
9ca98086 859 return offset;
e6c6c8f3 860
eea6121a 861 if (offset >= sec->rawsize)
f5fa8ca2 862 {
eea6121a 863 if (offset > sec->rawsize)
4eca0228 864 _bfd_error_handler
695344c0 865 /* xgettext:c-format */
d42c267e
AM
866 (_("%B: access beyond end of merged section (%Ld)"),
867 sec->owner, offset);
eea6121a 868 return secinfo->first_str ? sec->size : 0;
f5fa8ca2
JJ
869 }
870
871 if (secinfo->htab->strings)
872 {
873 if (sec->entsize == 1)
874 {
753731ee 875 p = secinfo->contents + offset - 1;
894bb1ee 876 while (p >= secinfo->contents && *p)
f5fa8ca2
JJ
877 --p;
878 ++p;
879 }
880 else
881 {
753731ee 882 p = secinfo->contents + (offset / sec->entsize) * sec->entsize;
f5fa8ca2
JJ
883 p -= sec->entsize;
884 while (p >= secinfo->contents)
885 {
886 unsigned int i;
887
888 for (i = 0; i < sec->entsize; ++i)
889 if (p[i] != '\0')
890 break;
891 if (i == sec->entsize)
892 break;
893 p -= sec->entsize;
894 }
895 p += sec->entsize;
896 }
897 }
898 else
899 {
753731ee 900 p = secinfo->contents + (offset / sec->entsize) * sec->entsize;
f5fa8ca2 901 }
9ca98086 902 entry = sec_merge_hash_lookup (secinfo->htab, (char *) p, 0, FALSE);
f5fa8ca2
JJ
903 if (!entry)
904 {
905 if (! secinfo->htab->strings)
906 abort ();
907 /* This should only happen if somebody points into the padding
908 after a NUL character but before next entity. */
909 if (*p)
910 abort ();
911 if (! secinfo->htab->first)
912 abort ();
913 entry = secinfo->htab->first;
753731ee
AM
914 p = (secinfo->contents + (offset / sec->entsize + 1) * sec->entsize
915 - entry->len);
f5fa8ca2
JJ
916 }
917
8550eb6e
JJ
918 *psec = entry->secinfo->sec;
919 return entry->u.index + (secinfo->contents + offset - p);
f5fa8ca2 920}
9f7c3e5e
AM
921
922/* Tidy up when done. */
923
924void
925_bfd_merge_sections_free (void *xsinfo)
926{
927 struct sec_merge_info *sinfo;
928
929 for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next)
930 {
931 bfd_hash_table_free (&sinfo->htab->table);
932 free (sinfo->htab);
933 }
934}