2002-11-30 Nathanael Nerode <neroden@gcc.gnu.org>
[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
d45913a0 356 return (boolean) (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
8550eb6e 386 align = bfd_get_section_alignment (sec->owner, sec);
a531bbd2
JJ
387 if ((sec->entsize < (unsigned int)(1 << align)
388 && ((sec->entsize & (sec->entsize - 1))
389 || !(sec->flags & SEC_STRINGS)))
390 || (sec->entsize > (unsigned int)(1 << align)
391 && (sec->entsize & ((1 << align) - 1))))
f5fa8ca2
JJ
392 {
393 /* Sanity check. If string character size is smaller than
394 alignment, then we require character size to be a power
395 of 2, otherwise character size must be integer multiple
a531bbd2
JJ
396 of alignment. For non-string constants, alignment must
397 be smaller than or equal to entity size and entity size
398 must be integer multiple of alignment. */
f5fa8ca2
JJ
399 return true;
400 }
401
f5fa8ca2 402 for (sinfo = (struct sec_merge_info *) *psinfo; sinfo; sinfo = sinfo->next)
8550eb6e
JJ
403 if ((secinfo = sinfo->chain)
404 && ! ((secinfo->sec->flags ^ sec->flags) & (SEC_MERGE | SEC_STRINGS))
405 && secinfo->sec->entsize == sec->entsize
406 && ! strcmp (secinfo->sec->name, sec->name))
f5fa8ca2
JJ
407 break;
408
409 if (sinfo == NULL)
410 {
411 /* Initialize the information we need to keep track of. */
699cb9b8
AM
412 amt = sizeof (struct sec_merge_info);
413 sinfo = (struct sec_merge_info *) bfd_alloc (abfd, amt);
f5fa8ca2
JJ
414 if (sinfo == NULL)
415 goto error_return;
416 sinfo->next = (struct sec_merge_info *) *psinfo;
8550eb6e 417 sinfo->chain = NULL;
f5fa8ca2 418 *psinfo = (PTR) sinfo;
699cb9b8 419 sinfo->htab = sec_merge_init (sec->entsize, (sec->flags & SEC_STRINGS));
f5fa8ca2
JJ
420 if (sinfo->htab == NULL)
421 goto error_return;
422 }
423
424 /* Read the section from abfd. */
425
dc810e39
AM
426 amt = sizeof (struct sec_merge_sec_info) + sec->_raw_size - 1;
427 *psecinfo = bfd_alloc (abfd, amt);
f5fa8ca2
JJ
428 if (*psecinfo == NULL)
429 goto error_return;
430
431 secinfo = (struct sec_merge_sec_info *)*psecinfo;
8550eb6e
JJ
432 if (sinfo->chain)
433 {
434 secinfo->next = sinfo->chain->next;
435 sinfo->chain->next = secinfo;
436 }
437 else
438 secinfo->next = secinfo;
439 sinfo->chain = secinfo;
440 secinfo->sec = sec;
441 secinfo->psecinfo = psecinfo;
f5fa8ca2 442 secinfo->htab = sinfo->htab;
f5fa8ca2
JJ
443 secinfo->first = NULL;
444
dc810e39
AM
445 if (! bfd_get_section_contents (sec->owner, sec, secinfo->contents,
446 (bfd_vma) 0, sec->_raw_size))
f5fa8ca2
JJ
447 goto error_return;
448
8550eb6e
JJ
449 return true;
450
451 error_return:
452 *psecinfo = NULL;
453 return false;
454}
455
456/* Compare two sec_merge_hash_entry structures. This is called via qsort. */
457
458static int
459cmplengthentry (a, b)
460 const PTR a;
461 const PTR b;
462{
463 struct sec_merge_hash_entry * A = *(struct sec_merge_hash_entry **) a;
464 struct sec_merge_hash_entry * B = *(struct sec_merge_hash_entry **) b;
dc810e39 465
8550eb6e
JJ
466 if (A->len < B->len)
467 return 1;
468 else if (A->len > B->len)
469 return -1;
470
471 return memcmp (A->root.string, B->root.string, A->len);
472}
473
474static int
475last4_eq (a, b)
a7b97311
AM
476 const PTR a;
477 const PTR b;
8550eb6e
JJ
478{
479 struct sec_merge_hash_entry * A = (struct sec_merge_hash_entry *) a;
480 struct sec_merge_hash_entry * B = (struct sec_merge_hash_entry *) b;
481
482 if (memcmp (A->root.string + A->len - 5 * A->u.entsize,
483 B->root.string + B->len - 5 * A->u.entsize,
484 4 * A->u.entsize) != 0)
485 /* This was a hashtable collision. */
486 return 0;
487
488 if (A->len <= B->len)
489 /* B cannot be a suffix of A unless A is equal to B, which is guaranteed
490 not to be equal by the hash table. */
491 return 0;
492
493 if (A->alignment < B->alignment
494 || ((A->len - B->len) & (B->alignment - 1)))
495 /* The suffix is not sufficiently aligned. */
496 return 0;
497
498 return memcmp (A->root.string + (A->len - B->len),
499 B->root.string, B->len - 5 * A->u.entsize) == 0;
500}
501
502static int
503last_eq (a, b)
a7b97311
AM
504 const PTR a;
505 const PTR b;
8550eb6e
JJ
506{
507 struct sec_merge_hash_entry * A = (struct sec_merge_hash_entry *) a;
508 struct sec_merge_hash_entry * B = (struct sec_merge_hash_entry *) b;
509
510 if (B->len >= 5 * A->u.entsize)
511 /* Longer strings are just pushed into the hash table,
512 they'll be used when looking up for very short strings. */
513 return 0;
514
515 if (memcmp (A->root.string + A->len - 2 * A->u.entsize,
516 B->root.string + B->len - 2 * A->u.entsize,
517 A->u.entsize) != 0)
518 /* This was a hashtable collision. */
519 return 0;
520
521 if (A->len <= B->len)
522 /* B cannot be a suffix of A unless A is equal to B, which is guaranteed
523 not to be equal by the hash table. */
524 return 0;
525
526 if (A->alignment < B->alignment
527 || ((A->len - B->len) & (B->alignment - 1)))
528 /* The suffix is not sufficiently aligned. */
529 return 0;
530
531 return memcmp (A->root.string + (A->len - B->len),
532 B->root.string, B->len - 2 * A->u.entsize) == 0;
533}
534
535/* Record one section into the hash table. */
536static boolean
537record_section (sinfo, secinfo)
538 struct sec_merge_info *sinfo;
539 struct sec_merge_sec_info *secinfo;
540{
541 asection *sec = secinfo->sec;
542 struct sec_merge_hash_entry *entry;
543 boolean nul;
544 unsigned char *p, *end;
545 bfd_vma mask, eltalign;
546 unsigned int align, i;
547
548 align = bfd_get_section_alignment (sec->owner, sec);
f5fa8ca2
JJ
549 end = secinfo->contents + sec->_raw_size;
550 nul = false;
dc810e39 551 mask = ((bfd_vma) 1 << align) - 1;
f5fa8ca2
JJ
552 if (sec->flags & SEC_STRINGS)
553 {
dc810e39 554 for (p = secinfo->contents; p < end; )
f5fa8ca2 555 {
a531bbd2
JJ
556 eltalign = p - secinfo->contents;
557 eltalign = ((eltalign ^ (eltalign - 1)) + 1) >> 1;
558 if (!eltalign || eltalign > mask)
559 eltalign = mask + 1;
dc810e39 560 entry = sec_merge_add (sinfo->htab, p, (unsigned) eltalign, secinfo);
8550eb6e
JJ
561 if (! entry)
562 goto error_return;
f5fa8ca2
JJ
563 p += entry->len;
564 if (sec->entsize == 1)
565 {
566 while (p < end && *p == 0)
567 {
568 if (!nul && !((p - secinfo->contents) & mask))
569 {
570 nul = true;
dc810e39
AM
571 entry = sec_merge_add (sinfo->htab, "",
572 (unsigned) mask + 1, secinfo);
8550eb6e
JJ
573 if (! entry)
574 goto error_return;
f5fa8ca2
JJ
575 }
576 p++;
577 }
578 }
579 else
580 {
581 while (p < end)
582 {
583 for (i = 0; i < sec->entsize; i++)
584 if (p[i] != '\0')
585 break;
586 if (i != sec->entsize)
587 break;
588 if (!nul && !((p - secinfo->contents) & mask))
589 {
590 nul = true;
dc810e39
AM
591 entry = sec_merge_add (sinfo->htab, p,
592 (unsigned) mask + 1, secinfo);
8550eb6e
JJ
593 if (! entry)
594 goto error_return;
f5fa8ca2
JJ
595 }
596 p += sec->entsize;
597 }
598 }
599 }
600 }
601 else
602 {
603 for (p = secinfo->contents; p < end; p += sec->entsize)
604 {
8550eb6e
JJ
605 entry = sec_merge_add (sinfo->htab, p, 1, secinfo);
606 if (! entry)
607 goto error_return;
608 }
609 }
610
611 return true;
612
613error_return:
614 for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
615 *secinfo->psecinfo = NULL;
616 return false;
617}
618
619/* This is a helper function for _bfd_merge_sections. It attempts to
620 merge strings matching suffixes of longer strings. */
621static void
622merge_strings (sinfo)
623 struct sec_merge_info *sinfo;
624{
625 struct sec_merge_hash_entry **array, **a, **end, *e;
626 struct sec_merge_sec_info *secinfo;
627 htab_t lasttab = NULL, last4tab = NULL;
dc810e39 628 bfd_size_type size, amt;
8550eb6e
JJ
629
630 /* Now sort the strings by length, longest first. */
dc810e39
AM
631 array = NULL;
632 amt = sinfo->htab->size * sizeof (struct sec_merge_hash_entry *);
633 array = (struct sec_merge_hash_entry **) bfd_malloc (amt);
8550eb6e
JJ
634 if (array == NULL)
635 goto alloc_failure;
636
637 for (e = sinfo->htab->first, a = array; e; e = e->next)
638 if (e->alignment)
639 *a++ = e;
640
641 sinfo->htab->size = a - array;
f5fa8ca2 642
dc810e39
AM
643 qsort (array, (size_t) sinfo->htab->size,
644 sizeof (struct sec_merge_hash_entry *), cmplengthentry);
8550eb6e 645
ebe3e2d1
NC
646 last4tab = htab_create_alloc ((size_t) sinfo->htab->size * 4,
647 NULL, last4_eq, NULL, calloc, free);
648 lasttab = htab_create_alloc ((size_t) sinfo->htab->size * 4,
649 NULL, last_eq, NULL, calloc, free);
8550eb6e
JJ
650 if (lasttab == NULL || last4tab == NULL)
651 goto alloc_failure;
652
653 /* Now insert the strings into hash tables (strings with last 4 characters
654 and strings with last character equal), look for longer strings which
655 we're suffix of. */
656 for (a = array, end = array + sinfo->htab->size; a < end; a++)
657 {
658 register hashval_t hash;
659 unsigned int c;
660 unsigned int i;
661 const unsigned char *s;
662 PTR *p;
663
664 e = *a;
665 e->u.entsize = sinfo->htab->entsize;
666 if (e->len <= e->u.entsize)
667 break;
668 if (e->len > 4 * e->u.entsize)
669 {
d45913a0 670 s = (const unsigned char *) (e->root.string + e->len - e->u.entsize);
8550eb6e
JJ
671 hash = 0;
672 for (i = 0; i < 4 * e->u.entsize; i++)
f5fa8ca2 673 {
8550eb6e
JJ
674 c = *--s;
675 hash += c + (c << 17);
676 hash ^= hash >> 2;
677 }
678 p = htab_find_slot_with_hash (last4tab, e, hash, INSERT);
679 if (p == NULL)
680 goto alloc_failure;
681 if (*p)
682 {
683 struct sec_merge_hash_entry *ent;
684
685 ent = (struct sec_merge_hash_entry *) *p;
686 e->u.suffix = ent;
687 e->alignment = 0;
688 continue;
f5fa8ca2 689 }
8550eb6e
JJ
690 else
691 *p = (PTR) e;
692 }
d45913a0 693 s = (const unsigned char *) (e->root.string + e->len - e->u.entsize);
8550eb6e
JJ
694 hash = 0;
695 for (i = 0; i < e->u.entsize; i++)
696 {
697 c = *--s;
698 hash += c + (c << 17);
699 hash ^= hash >> 2;
700 }
701 p = htab_find_slot_with_hash (lasttab, e, hash, INSERT);
702 if (p == NULL)
703 goto alloc_failure;
704 if (*p)
705 {
706 struct sec_merge_hash_entry *ent;
707
708 ent = (struct sec_merge_hash_entry *) *p;
709 e->u.suffix = ent;
710 e->alignment = 0;
f5fa8ca2 711 }
8550eb6e
JJ
712 else
713 *p = (PTR) e;
f5fa8ca2
JJ
714 }
715
8550eb6e
JJ
716alloc_failure:
717 if (array)
718 free (array);
719 if (lasttab)
720 htab_delete (lasttab);
721 if (last4tab)
722 htab_delete (last4tab);
723
724 /* Now assign positions to the strings we want to keep. */
725 size = 0;
726 secinfo = sinfo->htab->first->secinfo;
727 for (e = sinfo->htab->first; e; e = e->next)
728 {
729 if (e->secinfo != secinfo)
730 {
731 secinfo->sec->_cooked_size = size;
732 secinfo = e->secinfo;
733 }
734 if (e->alignment)
735 {
736 if (e->secinfo->first == NULL)
737 {
738 e->secinfo->first = e;
739 size = 0;
740 }
741 size = (size + e->alignment - 1) & ~((bfd_vma) e->alignment - 1);
742 e->u.index = size;
743 size += e->len;
744 }
745 }
746 secinfo->sec->_cooked_size = size;
747
748 /* And now adjust the rest, removing them from the chain (but not hashtable)
749 at the same time. */
750 for (a = &sinfo->htab->first, e = *a; e; e = e->next)
751 if (e->alignment)
752 a = &e->next;
753 else
754 {
755 *a = e->next;
756 if (e->len)
757 {
758 e->secinfo = e->u.suffix->secinfo;
759 e->alignment = e->u.suffix->alignment;
760 e->u.index = e->u.suffix->u.index + (e->u.suffix->len - e->len);
761 }
762 }
763}
f5fa8ca2 764
8550eb6e
JJ
765/* This function is called once after all SEC_MERGE sections are registered
766 with _bfd_merge_section. */
767
768boolean
d3c456e9 769_bfd_merge_sections (abfd, xsinfo, remove_hook)
8550eb6e
JJ
770 bfd *abfd ATTRIBUTE_UNUSED;
771 PTR xsinfo;
d3c456e9 772 void (*remove_hook) PARAMS((bfd *, asection *));
8550eb6e
JJ
773{
774 struct sec_merge_info *sinfo;
775
776 for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next)
777 {
778 struct sec_merge_sec_info * secinfo;
779
780 if (! sinfo->chain)
781 continue;
782
783 /* Move sinfo->chain to head of the chain, terminate it. */
784 secinfo = sinfo->chain;
785 sinfo->chain = secinfo->next;
786 secinfo->next = NULL;
787
788 /* Record the sections into the hash table. */
789 for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
790 if (secinfo->sec->flags & SEC_EXCLUDE)
d3c456e9
JJ
791 {
792 *secinfo->psecinfo = NULL;
793 if (remove_hook)
794 (*remove_hook) (abfd, secinfo->sec);
795 }
8550eb6e
JJ
796 else if (! record_section (sinfo, secinfo))
797 break;
798
799 if (secinfo)
800 continue;
801
86eaf01e
JJ
802 if (sinfo->htab->first == NULL)
803 continue;
804
8550eb6e
JJ
805 if (sinfo->htab->strings)
806 merge_strings (sinfo);
807 else
808 {
809 struct sec_merge_hash_entry *e;
810 bfd_size_type size = 0;
811
812 /* Things are much simpler for non-strings.
813 Just assign them slots in the section. */
814 secinfo = NULL;
815 for (e = sinfo->htab->first; e; e = e->next)
816 {
817 if (e->secinfo->first == NULL)
818 {
819 if (secinfo)
820 secinfo->sec->_cooked_size = size;
821 e->secinfo->first = e;
822 size = 0;
823 }
824 size = (size + e->alignment - 1)
825 & ~((bfd_vma) e->alignment - 1);
826 e->u.index = size;
827 size += e->len;
828 secinfo = e->secinfo;
829 }
830 secinfo->sec->_cooked_size = size;
831 }
832
833 /* Finally shrink all input sections which have not made it into
834 the hash table at all. */
835 for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
836 if (secinfo->first == NULL)
699cb9b8 837 secinfo->sec->_cooked_size = 0;
8550eb6e
JJ
838 }
839
840 return true;
f5fa8ca2
JJ
841}
842
843/* Write out the merged section. */
844
845boolean
846_bfd_write_merged_section (output_bfd, sec, psecinfo)
847 bfd *output_bfd;
848 asection *sec;
849 PTR psecinfo;
850{
851 struct sec_merge_sec_info *secinfo;
dc810e39 852 file_ptr pos;
f5fa8ca2
JJ
853
854 secinfo = (struct sec_merge_sec_info *) psecinfo;
855
856 if (!secinfo->first)
857 return true;
858
dc810e39
AM
859 pos = sec->output_section->filepos + sec->output_offset;
860 if (bfd_seek (output_bfd, pos, SEEK_SET) != 0)
f5fa8ca2
JJ
861 return false;
862
a531bbd2 863 if (! sec_merge_emit (output_bfd, secinfo->first))
f5fa8ca2
JJ
864 return false;
865
866 return true;
867}
868
869/* Adjust an address in the SEC_MERGE section. Given OFFSET within
870 *PSEC, this returns the new offset in the adjusted SEC_MERGE
871 section and writes the new section back into *PSEC. */
872
873bfd_vma
874_bfd_merged_section_offset (output_bfd, psec, psecinfo, offset, addend)
875 bfd *output_bfd ATTRIBUTE_UNUSED;
876 asection **psec;
877 PTR psecinfo;
878 bfd_vma offset, addend;
879{
880 struct sec_merge_sec_info *secinfo;
881 struct sec_merge_hash_entry *entry;
882 unsigned char *p;
883 asection *sec = *psec;
884
885 secinfo = (struct sec_merge_sec_info *) psecinfo;
886
887 if (offset + addend >= sec->_raw_size)
888 {
889 if (offset + addend > sec->_raw_size)
923f08ff
AM
890 {
891 (*_bfd_error_handler)
892 (_("%s: access beyond end of merged section (%ld + %ld)"),
893 bfd_get_filename (sec->owner), (long) offset, (long) addend);
894 }
f5fa8ca2
JJ
895 return (secinfo->first ? sec->_cooked_size : 0);
896 }
897
898 if (secinfo->htab->strings)
899 {
900 if (sec->entsize == 1)
901 {
902 p = secinfo->contents + offset + addend - 1;
894bb1ee 903 while (p >= secinfo->contents && *p)
f5fa8ca2
JJ
904 --p;
905 ++p;
906 }
907 else
908 {
909 p = secinfo->contents
910 + ((offset + addend) / sec->entsize) * sec->entsize;
911 p -= sec->entsize;
912 while (p >= secinfo->contents)
913 {
914 unsigned int i;
915
916 for (i = 0; i < sec->entsize; ++i)
917 if (p[i] != '\0')
918 break;
919 if (i == sec->entsize)
920 break;
921 p -= sec->entsize;
922 }
923 p += sec->entsize;
924 }
925 }
926 else
927 {
928 p = secinfo->contents
929 + ((offset + addend) / sec->entsize) * sec->entsize;
930 }
a531bbd2 931 entry = sec_merge_hash_lookup (secinfo->htab, p, 0, false);
f5fa8ca2
JJ
932 if (!entry)
933 {
934 if (! secinfo->htab->strings)
935 abort ();
936 /* This should only happen if somebody points into the padding
937 after a NUL character but before next entity. */
938 if (*p)
939 abort ();
940 if (! secinfo->htab->first)
941 abort ();
942 entry = secinfo->htab->first;
943 p = secinfo->contents
944 + ((offset + addend) / sec->entsize + 1) * sec->entsize
945 - entry->len;
946 }
947
8550eb6e
JJ
948 *psec = entry->secinfo->sec;
949 return entry->u.index + (secinfo->contents + offset - p);
f5fa8ca2 950}
This page took 0.247282 seconds and 4 git commands to generate.