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