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