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