Slightly improve logic of some operations on stap-probe.c
[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
ddb2b442
AM
558static int
559strrevcmp (const void *a, const void *b)
560{
561 struct sec_merge_hash_entry *A = *(struct sec_merge_hash_entry **) a;
562 struct sec_merge_hash_entry *B = *(struct sec_merge_hash_entry **) b;
563 unsigned int lenA = A->len;
564 unsigned int lenB = B->len;
f075ee0c
AM
565 const unsigned char *s = (const unsigned char *) A->root.string + lenA - 1;
566 const unsigned char *t = (const unsigned char *) B->root.string + lenB - 1;
ddb2b442
AM
567 int l = lenA < lenB ? lenA : lenB;
568
569 while (l)
570 {
571 if (*s != *t)
572 return (int) *s - (int) *t;
573 s--;
574 t--;
575 l--;
576 }
577 return lenA - lenB;
578}
579
580/* Like strrevcmp, but for the case where all strings have the same
581 alignment > entsize. */
582
583static int
584strrevcmp_align (const void *a, const void *b)
585{
586 struct sec_merge_hash_entry *A = *(struct sec_merge_hash_entry **) a;
587 struct sec_merge_hash_entry *B = *(struct sec_merge_hash_entry **) b;
588 unsigned int lenA = A->len;
589 unsigned int lenB = B->len;
f075ee0c
AM
590 const unsigned char *s = (const unsigned char *) A->root.string + lenA - 1;
591 const unsigned char *t = (const unsigned char *) B->root.string + lenB - 1;
ddb2b442
AM
592 int l = lenA < lenB ? lenA : lenB;
593 int tail_align = (lenA & (A->alignment - 1)) - (lenB & (A->alignment - 1));
594
595 if (tail_align != 0)
596 return tail_align;
597
598 while (l)
599 {
600 if (*s != *t)
601 return (int) *s - (int) *t;
602 s--;
603 t--;
604 l--;
605 }
606 return lenA - lenB;
607}
608
609static inline int
610is_suffix (const struct sec_merge_hash_entry *A,
611 const struct sec_merge_hash_entry *B)
612{
613 if (A->len <= B->len)
614 /* B cannot be a suffix of A unless A is equal to B, which is guaranteed
615 not to be equal by the hash table. */
616 return 0;
617
618 return memcmp (A->root.string + (A->len - B->len),
619 B->root.string, B->len) == 0;
620}
621
8550eb6e
JJ
622/* This is a helper function for _bfd_merge_sections. It attempts to
623 merge strings matching suffixes of longer strings. */
ebd2263b 624static struct sec_merge_sec_info *
ac0e732e 625merge_strings (struct sec_merge_info *sinfo)
8550eb6e 626{
ddb2b442 627 struct sec_merge_hash_entry **array, **a, *e;
8550eb6e 628 struct sec_merge_sec_info *secinfo;
dc810e39 629 bfd_size_type size, amt;
ddb2b442 630 unsigned int alignment = 0;
8550eb6e 631
ddb2b442 632 /* Now sort the strings */
dc810e39 633 amt = sinfo->htab->size * sizeof (struct sec_merge_hash_entry *);
a50b1753 634 array = (struct sec_merge_hash_entry **) bfd_malloc (amt);
8550eb6e 635 if (array == NULL)
ebd2263b 636 return NULL;
8550eb6e
JJ
637
638 for (e = sinfo->htab->first, a = array; e; e = e->next)
639 if (e->alignment)
ddb2b442
AM
640 {
641 *a++ = e;
642 /* Adjust the length to not include the zero terminator. */
643 e->len -= sinfo->htab->entsize;
644 if (alignment != e->alignment)
645 {
646 if (alignment == 0)
647 alignment = e->alignment;
648 else
649 alignment = (unsigned) -1;
650 }
651 }
8550eb6e
JJ
652
653 sinfo->htab->size = a - array;
ddb2b442 654 if (sinfo->htab->size != 0)
8550eb6e 655 {
ddb2b442
AM
656 qsort (array, (size_t) sinfo->htab->size,
657 sizeof (struct sec_merge_hash_entry *),
658 (alignment != (unsigned) -1 && alignment > sinfo->htab->entsize
659 ? strrevcmp_align : strrevcmp));
660
661 /* Loop over the sorted array and merge suffixes */
662 e = *--a;
663 e->len += sinfo->htab->entsize;
664 while (--a >= array)
8550eb6e 665 {
ddb2b442 666 struct sec_merge_hash_entry *cmp = *a;
8550eb6e 667
ddb2b442
AM
668 cmp->len += sinfo->htab->entsize;
669 if (e->alignment >= cmp->alignment
670 && !((e->len - cmp->len) & (cmp->alignment - 1))
671 && is_suffix (e, cmp))
672 {
673 cmp->u.suffix = e;
674 cmp->alignment = 0;
f5fa8ca2 675 }
8550eb6e 676 else
ddb2b442 677 e = cmp;
8550eb6e 678 }
f5fa8ca2
JJ
679 }
680
f6ac8c52 681 free (array);
8550eb6e
JJ
682
683 /* Now assign positions to the strings we want to keep. */
684 size = 0;
685 secinfo = sinfo->htab->first->secinfo;
686 for (e = sinfo->htab->first; e; e = e->next)
687 {
688 if (e->secinfo != secinfo)
689 {
eea6121a 690 secinfo->sec->size = size;
8550eb6e
JJ
691 secinfo = e->secinfo;
692 }
693 if (e->alignment)
694 {
57ceae94 695 if (e->secinfo->first_str == NULL)
8550eb6e 696 {
57ceae94 697 e->secinfo->first_str = e;
8550eb6e
JJ
698 size = 0;
699 }
700 size = (size + e->alignment - 1) & ~((bfd_vma) e->alignment - 1);
701 e->u.index = size;
702 size += e->len;
703 }
704 }
eea6121a 705 secinfo->sec->size = size;
8550eb6e
JJ
706
707 /* And now adjust the rest, removing them from the chain (but not hashtable)
708 at the same time. */
709 for (a = &sinfo->htab->first, e = *a; e; e = e->next)
710 if (e->alignment)
711 a = &e->next;
712 else
713 {
714 *a = e->next;
715 if (e->len)
716 {
717 e->secinfo = e->u.suffix->secinfo;
718 e->alignment = e->u.suffix->alignment;
719 e->u.index = e->u.suffix->u.index + (e->u.suffix->len - e->len);
720 }
721 }
ebd2263b 722 return secinfo;
8550eb6e 723}
f5fa8ca2 724
8550eb6e
JJ
725/* This function is called once after all SEC_MERGE sections are registered
726 with _bfd_merge_section. */
727
b34976b6 728bfd_boolean
e6c6c8f3 729_bfd_merge_sections (bfd *abfd,
8423293d
AM
730 struct bfd_link_info *info ATTRIBUTE_UNUSED,
731 void *xsinfo,
732 void (*remove_hook) (bfd *, asection *))
8550eb6e
JJ
733{
734 struct sec_merge_info *sinfo;
735
736 for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next)
737 {
ebd2263b
AM
738 struct sec_merge_sec_info *secinfo;
739 bfd_size_type align;
8550eb6e
JJ
740
741 if (! sinfo->chain)
742 continue;
743
744 /* Move sinfo->chain to head of the chain, terminate it. */
745 secinfo = sinfo->chain;
746 sinfo->chain = secinfo->next;
747 secinfo->next = NULL;
748
749 /* Record the sections into the hash table. */
ebd2263b 750 align = 1;
8550eb6e
JJ
751 for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
752 if (secinfo->sec->flags & SEC_EXCLUDE)
d3c456e9
JJ
753 {
754 *secinfo->psecinfo = NULL;
755 if (remove_hook)
756 (*remove_hook) (abfd, secinfo->sec);
757 }
ebd2263b
AM
758 else
759 {
760 if (!record_section (sinfo, secinfo))
761 return FALSE;
762 if (align)
763 {
764 align = (bfd_size_type) 1 << secinfo->sec->alignment_power;
765 if ((secinfo->sec->size & (align - 1)) != 0)
766 align = 0;
767 }
768 }
8550eb6e 769
86eaf01e
JJ
770 if (sinfo->htab->first == NULL)
771 continue;
772
8550eb6e 773 if (sinfo->htab->strings)
f6ac8c52 774 {
ebd2263b
AM
775 secinfo = merge_strings (sinfo);
776 if (!secinfo)
f6ac8c52
AM
777 return FALSE;
778 }
8550eb6e
JJ
779 else
780 {
781 struct sec_merge_hash_entry *e;
782 bfd_size_type size = 0;
783
784 /* Things are much simpler for non-strings.
785 Just assign them slots in the section. */
786 secinfo = NULL;
787 for (e = sinfo->htab->first; e; e = e->next)
788 {
57ceae94 789 if (e->secinfo->first_str == NULL)
8550eb6e
JJ
790 {
791 if (secinfo)
eea6121a 792 secinfo->sec->size = size;
57ceae94 793 e->secinfo->first_str = e;
8550eb6e
JJ
794 size = 0;
795 }
ebd2263b 796 size = (size + e->alignment - 1) & ~((bfd_vma) e->alignment - 1);
8550eb6e
JJ
797 e->u.index = size;
798 size += e->len;
799 secinfo = e->secinfo;
800 }
eea6121a 801 secinfo->sec->size = size;
8550eb6e
JJ
802 }
803
ebd2263b
AM
804 /* If the input sections were padded according to their alignments,
805 then pad the output too. */
806 if (align)
807 secinfo->sec->size = (secinfo->sec->size + align - 1) & -align;
808
809 /* Finally remove all input sections which have not made it into
810 the hash table at all. */
811 for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
812 if (secinfo->first_str == NULL)
813 secinfo->sec->flags |= SEC_EXCLUDE | SEC_KEEP;
8550eb6e
JJ
814 }
815
b34976b6 816 return TRUE;
f5fa8ca2
JJ
817}
818
819/* Write out the merged section. */
820
b34976b6 821bfd_boolean
ac0e732e 822_bfd_write_merged_section (bfd *output_bfd, asection *sec, void *psecinfo)
f5fa8ca2
JJ
823{
824 struct sec_merge_sec_info *secinfo;
dc810e39 825 file_ptr pos;
0ce398f1
L
826 unsigned char *contents;
827 Elf_Internal_Shdr *hdr;
f5fa8ca2
JJ
828
829 secinfo = (struct sec_merge_sec_info *) psecinfo;
830
e6c6c8f3
JM
831 if (!secinfo)
832 return FALSE;
833
57ceae94 834 if (secinfo->first_str == NULL)
b34976b6 835 return TRUE;
f5fa8ca2 836
5dabe785 837 /* FIXME: octets_per_byte. */
0ce398f1
L
838 hdr = &elf_section_data (sec->output_section)->this_hdr;
839 if (hdr->sh_offset == (file_ptr) -1)
840 {
841 /* We must compress this section. Write output to the
842 buffer. */
843 contents = hdr->contents;
844 if ((sec->output_section->flags & SEC_ELF_COMPRESS) == 0
845 || contents == NULL)
846 abort ();
847 }
848 else
849 {
850 contents = NULL;
851 pos = sec->output_section->filepos + sec->output_offset;
852 if (bfd_seek (output_bfd, pos, SEEK_SET) != 0)
853 return FALSE;
854 }
f5fa8ca2 855
0ce398f1
L
856 if (! sec_merge_emit (output_bfd, secinfo->first_str, contents,
857 sec->output_offset))
b34976b6 858 return FALSE;
f5fa8ca2 859
b34976b6 860 return TRUE;
f5fa8ca2
JJ
861}
862
863/* Adjust an address in the SEC_MERGE section. Given OFFSET within
864 *PSEC, this returns the new offset in the adjusted SEC_MERGE
865 section and writes the new section back into *PSEC. */
866
867bfd_vma
ac0e732e 868_bfd_merged_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED, asection **psec,
753731ee 869 void *psecinfo, bfd_vma offset)
f5fa8ca2
JJ
870{
871 struct sec_merge_sec_info *secinfo;
872 struct sec_merge_hash_entry *entry;
873 unsigned char *p;
874 asection *sec = *psec;
875
876 secinfo = (struct sec_merge_sec_info *) psecinfo;
877
e6c6c8f3 878 if (!secinfo)
9ca98086 879 return offset;
e6c6c8f3 880
eea6121a 881 if (offset >= sec->rawsize)
f5fa8ca2 882 {
eea6121a 883 if (offset > sec->rawsize)
4eca0228 884 _bfd_error_handler
695344c0 885 /* xgettext:c-format */
2dcf00ce
AM
886 (_("%pB: access beyond end of merged section (%" PRId64 ")"),
887 sec->owner, (int64_t) offset);
eea6121a 888 return secinfo->first_str ? sec->size : 0;
f5fa8ca2
JJ
889 }
890
891 if (secinfo->htab->strings)
892 {
893 if (sec->entsize == 1)
894 {
753731ee 895 p = secinfo->contents + offset - 1;
894bb1ee 896 while (p >= secinfo->contents && *p)
f5fa8ca2
JJ
897 --p;
898 ++p;
899 }
900 else
901 {
753731ee 902 p = secinfo->contents + (offset / sec->entsize) * sec->entsize;
f5fa8ca2
JJ
903 p -= sec->entsize;
904 while (p >= secinfo->contents)
905 {
906 unsigned int i;
907
908 for (i = 0; i < sec->entsize; ++i)
909 if (p[i] != '\0')
910 break;
911 if (i == sec->entsize)
912 break;
913 p -= sec->entsize;
914 }
915 p += sec->entsize;
916 }
917 }
918 else
919 {
753731ee 920 p = secinfo->contents + (offset / sec->entsize) * sec->entsize;
f5fa8ca2 921 }
9ca98086 922 entry = sec_merge_hash_lookup (secinfo->htab, (char *) p, 0, FALSE);
f5fa8ca2
JJ
923 if (!entry)
924 {
925 if (! secinfo->htab->strings)
926 abort ();
927 /* This should only happen if somebody points into the padding
928 after a NUL character but before next entity. */
929 if (*p)
930 abort ();
931 if (! secinfo->htab->first)
932 abort ();
933 entry = secinfo->htab->first;
753731ee
AM
934 p = (secinfo->contents + (offset / sec->entsize + 1) * sec->entsize
935 - entry->len);
f5fa8ca2
JJ
936 }
937
8550eb6e
JJ
938 *psec = entry->secinfo->sec;
939 return entry->u.index + (secinfo->contents + offset - p);
f5fa8ca2 940}
9f7c3e5e
AM
941
942/* Tidy up when done. */
943
944void
945_bfd_merge_sections_free (void *xsinfo)
946{
947 struct sec_merge_info *sinfo;
948
949 for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next)
950 {
951 bfd_hash_table_free (&sinfo->htab->table);
952 free (sinfo->htab);
953 }
954}
This page took 2.411328 seconds and 4 git commands to generate.