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