Use std::vector on tdesc->reg_defs (gdbserver/tdesc.h)
[deliverable/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. */
612static void
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
JJ
623 if (array == NULL)
624 goto alloc_failure;
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
8550eb6e
JJ
669alloc_failure:
670 if (array)
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 }
717}
f5fa8ca2 718
8550eb6e
JJ
719/* This function is called once after all SEC_MERGE sections are registered
720 with _bfd_merge_section. */
721
b34976b6 722bfd_boolean
e6c6c8f3 723_bfd_merge_sections (bfd *abfd,
8423293d
AM
724 struct bfd_link_info *info ATTRIBUTE_UNUSED,
725 void *xsinfo,
726 void (*remove_hook) (bfd *, asection *))
8550eb6e
JJ
727{
728 struct sec_merge_info *sinfo;
729
730 for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next)
731 {
732 struct sec_merge_sec_info * secinfo;
733
734 if (! sinfo->chain)
735 continue;
736
737 /* Move sinfo->chain to head of the chain, terminate it. */
738 secinfo = sinfo->chain;
739 sinfo->chain = secinfo->next;
740 secinfo->next = NULL;
741
742 /* Record the sections into the hash table. */
743 for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
744 if (secinfo->sec->flags & SEC_EXCLUDE)
d3c456e9
JJ
745 {
746 *secinfo->psecinfo = NULL;
747 if (remove_hook)
748 (*remove_hook) (abfd, secinfo->sec);
749 }
9ca98086 750 else if (! record_section (sinfo, secinfo))
8550eb6e
JJ
751 break;
752
753 if (secinfo)
754 continue;
755
86eaf01e
JJ
756 if (sinfo->htab->first == NULL)
757 continue;
758
8550eb6e
JJ
759 if (sinfo->htab->strings)
760 merge_strings (sinfo);
761 else
762 {
763 struct sec_merge_hash_entry *e;
764 bfd_size_type size = 0;
765
766 /* Things are much simpler for non-strings.
767 Just assign them slots in the section. */
768 secinfo = NULL;
769 for (e = sinfo->htab->first; e; e = e->next)
770 {
57ceae94 771 if (e->secinfo->first_str == NULL)
8550eb6e
JJ
772 {
773 if (secinfo)
eea6121a 774 secinfo->sec->size = size;
57ceae94 775 e->secinfo->first_str = e;
8550eb6e
JJ
776 size = 0;
777 }
778 size = (size + e->alignment - 1)
779 & ~((bfd_vma) e->alignment - 1);
780 e->u.index = size;
781 size += e->len;
782 secinfo = e->secinfo;
783 }
eea6121a 784 secinfo->sec->size = size;
8550eb6e
JJ
785 }
786
27c630ba 787 /* Finally remove all input sections which have not made it into
8550eb6e
JJ
788 the hash table at all. */
789 for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
57ceae94 790 if (secinfo->first_str == NULL)
a14a5de3 791 secinfo->sec->flags |= SEC_EXCLUDE | SEC_KEEP;
8550eb6e
JJ
792 }
793
b34976b6 794 return TRUE;
f5fa8ca2
JJ
795}
796
797/* Write out the merged section. */
798
b34976b6 799bfd_boolean
ac0e732e 800_bfd_write_merged_section (bfd *output_bfd, asection *sec, void *psecinfo)
f5fa8ca2
JJ
801{
802 struct sec_merge_sec_info *secinfo;
dc810e39 803 file_ptr pos;
0ce398f1
L
804 unsigned char *contents;
805 Elf_Internal_Shdr *hdr;
f5fa8ca2
JJ
806
807 secinfo = (struct sec_merge_sec_info *) psecinfo;
808
e6c6c8f3
JM
809 if (!secinfo)
810 return FALSE;
811
57ceae94 812 if (secinfo->first_str == NULL)
b34976b6 813 return TRUE;
f5fa8ca2 814
5dabe785 815 /* FIXME: octets_per_byte. */
0ce398f1
L
816 hdr = &elf_section_data (sec->output_section)->this_hdr;
817 if (hdr->sh_offset == (file_ptr) -1)
818 {
819 /* We must compress this section. Write output to the
820 buffer. */
821 contents = hdr->contents;
822 if ((sec->output_section->flags & SEC_ELF_COMPRESS) == 0
823 || contents == NULL)
824 abort ();
825 }
826 else
827 {
828 contents = NULL;
829 pos = sec->output_section->filepos + sec->output_offset;
830 if (bfd_seek (output_bfd, pos, SEEK_SET) != 0)
831 return FALSE;
832 }
f5fa8ca2 833
0ce398f1
L
834 if (! sec_merge_emit (output_bfd, secinfo->first_str, contents,
835 sec->output_offset))
b34976b6 836 return FALSE;
f5fa8ca2 837
b34976b6 838 return TRUE;
f5fa8ca2
JJ
839}
840
841/* Adjust an address in the SEC_MERGE section. Given OFFSET within
842 *PSEC, this returns the new offset in the adjusted SEC_MERGE
843 section and writes the new section back into *PSEC. */
844
845bfd_vma
ac0e732e 846_bfd_merged_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED, asection **psec,
753731ee 847 void *psecinfo, bfd_vma offset)
f5fa8ca2
JJ
848{
849 struct sec_merge_sec_info *secinfo;
850 struct sec_merge_hash_entry *entry;
851 unsigned char *p;
852 asection *sec = *psec;
853
854 secinfo = (struct sec_merge_sec_info *) psecinfo;
855
e6c6c8f3 856 if (!secinfo)
9ca98086 857 return offset;
e6c6c8f3 858
eea6121a 859 if (offset >= sec->rawsize)
f5fa8ca2 860 {
eea6121a 861 if (offset > sec->rawsize)
4eca0228 862 _bfd_error_handler
695344c0 863 /* xgettext:c-format */
d42c267e
AM
864 (_("%B: access beyond end of merged section (%Ld)"),
865 sec->owner, offset);
eea6121a 866 return secinfo->first_str ? sec->size : 0;
f5fa8ca2
JJ
867 }
868
869 if (secinfo->htab->strings)
870 {
871 if (sec->entsize == 1)
872 {
753731ee 873 p = secinfo->contents + offset - 1;
894bb1ee 874 while (p >= secinfo->contents && *p)
f5fa8ca2
JJ
875 --p;
876 ++p;
877 }
878 else
879 {
753731ee 880 p = secinfo->contents + (offset / sec->entsize) * sec->entsize;
f5fa8ca2
JJ
881 p -= sec->entsize;
882 while (p >= secinfo->contents)
883 {
884 unsigned int i;
885
886 for (i = 0; i < sec->entsize; ++i)
887 if (p[i] != '\0')
888 break;
889 if (i == sec->entsize)
890 break;
891 p -= sec->entsize;
892 }
893 p += sec->entsize;
894 }
895 }
896 else
897 {
753731ee 898 p = secinfo->contents + (offset / sec->entsize) * sec->entsize;
f5fa8ca2 899 }
9ca98086 900 entry = sec_merge_hash_lookup (secinfo->htab, (char *) p, 0, FALSE);
f5fa8ca2
JJ
901 if (!entry)
902 {
903 if (! secinfo->htab->strings)
904 abort ();
905 /* This should only happen if somebody points into the padding
906 after a NUL character but before next entity. */
907 if (*p)
908 abort ();
909 if (! secinfo->htab->first)
910 abort ();
911 entry = secinfo->htab->first;
753731ee
AM
912 p = (secinfo->contents + (offset / sec->entsize + 1) * sec->entsize
913 - entry->len);
f5fa8ca2
JJ
914 }
915
8550eb6e
JJ
916 *psec = entry->secinfo->sec;
917 return entry->u.index + (secinfo->contents + offset - p);
f5fa8ca2 918}
9f7c3e5e
AM
919
920/* Tidy up when done. */
921
922void
923_bfd_merge_sections_free (void *xsinfo)
924{
925 struct sec_merge_info *sinfo;
926
927 for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next)
928 {
929 bfd_hash_table_free (&sinfo->htab->table);
930 free (sinfo->htab);
931 }
932}
This page took 0.892491 seconds and 4 git commands to generate.