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