OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [bfd/] [merge.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1181 sfurman
/* SEC_MERGE support.
2
   Copyright 2001, 2002 Free Software Foundation, Inc.
3
   Written by Jakub Jelinek <jakub@redhat.com>.
4
 
5
   This file is part of BFD, the Binary File Descriptor library.
6
 
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.
11
 
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.
16
 
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.  */
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"
27
#include "hashtab.h"
28
#include "libiberty.h"
29
 
30
struct sec_merge_sec_info;
31
 
32
/* An entry in the section merge hash table.  */
33
 
34
struct sec_merge_hash_entry
35
{
36
  struct bfd_hash_entry root;
37
  /* Length of this entry.  */
38
  unsigned int len;
39
  /* Start of this string needs to be aligned to
40
     alignment octets (not 1 << align).  */
41
  unsigned int alignment;
42
  union
43
  {
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;
51
  /* Which section is it in.  */
52
  struct sec_merge_sec_info *secinfo;
53
  /* Next entity in the hash table.  */
54
  struct sec_merge_hash_entry *next;
55
};
56
 
57
/* The section merge hash table.  */
58
 
59
struct 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;
70
  /* Are entries fixed size or zero terminated strings?  */
71
  boolean strings;
72
};
73
 
74
struct sec_merge_info
75
{
76
  /* Chain of sec_merge_infos.  */
77
  struct sec_merge_info *next;
78
  /* Chain of sec_merge_sec_infos.  */
79
  struct sec_merge_sec_info *chain;
80
  /* A hash table used to hold section content.  */
81
  struct sec_merge_hash *htab;
82
};
83
 
84
struct sec_merge_sec_info
85
{
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;
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
 
100
static struct bfd_hash_entry *sec_merge_hash_newfunc
101
  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
102
static struct sec_merge_hash_entry *sec_merge_hash_lookup
103
  PARAMS ((struct sec_merge_hash *, const char *, unsigned int, boolean));
104
static struct sec_merge_hash *sec_merge_init
105
  PARAMS ((unsigned int, boolean));
106
static struct sec_merge_hash_entry *sec_merge_add
107
  PARAMS ((struct sec_merge_hash *, const char *, unsigned int,
108
           struct sec_merge_sec_info *));
109
static boolean sec_merge_emit
110
  PARAMS ((bfd *, struct sec_merge_hash_entry *));
111
static int cmplengthentry PARAMS ((const PTR, const PTR));
112
static int last4_eq PARAMS ((const PTR, const PTR));
113
static int last_eq PARAMS ((const PTR, const PTR));
114
static boolean record_section
115
  PARAMS ((struct sec_merge_info *, struct sec_merge_sec_info *));
116
static void merge_strings PARAMS ((struct sec_merge_info *));
117
 
118
/* Routine to create an entry in a section merge hashtab.  */
119
 
120
static struct bfd_hash_entry *
121
sec_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.  */
143
      ret->u.suffix = NULL;
144
      ret->alignment = 0;
145
      ret->secinfo = NULL;
146
      ret->next = NULL;
147
    }
148
 
149
  return (struct bfd_hash_entry *) ret;
150
}
151
 
152
/* Look up an entry in a section merge hash table.  */
153
 
154
static struct sec_merge_hash_entry *
155
sec_merge_hash_lookup (table, string, alignment, create)
156
     struct sec_merge_hash *table;
157
     const char *string;
158
     unsigned int alignment;
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;
205
    }
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;
220
       hashp = (struct sec_merge_hash_entry *) hashp->root.next)
221
    {
222
      if (hashp->root.hash == hash
223
          && len == hashp->len
224
          && memcmp (hashp->root.string, string, len) == 0)
225
        {
226
          /* If the string we found does not have at least the required
227
             alignment, we need to insert another copy.  */
228
          if (hashp->alignment < alignment)
229
            {
230
              /*  Mark the less aligned copy as deleted.  */
231
              hashp->len = 0;
232
              hashp->alignment = 0;
233
              break;
234
            }
235
          return hashp;
236
        }
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;
250
  hashp->alignment = alignment;
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
 
259
static struct sec_merge_hash *
260
sec_merge_init (entsize, strings)
261
     unsigned int entsize;
262
     boolean strings;
263
{
264
  struct sec_merge_hash *table;
265
  bfd_size_type amt = sizeof (struct sec_merge_hash);
266
 
267
  table = (struct sec_merge_hash *) bfd_malloc (amt);
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;
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
 
289
static struct sec_merge_hash_entry *
290
sec_merge_add (tab, str, alignment, secinfo)
291
     struct sec_merge_hash *tab;
292
     const char *str;
293
     unsigned int alignment;
294
     struct sec_merge_sec_info *secinfo;
295
{
296
  register struct sec_merge_hash_entry *entry;
297
 
298
  entry = sec_merge_hash_lookup (tab, str, alignment, true);
299
  if (entry == NULL)
300
    return NULL;
301
 
302
  if (entry->secinfo == NULL)
303
    {
304
      tab->size++;
305
      entry->secinfo = secinfo;
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
 
316
static boolean
317
sec_merge_emit (abfd, entry)
318
     register bfd *abfd;
319
     struct sec_merge_hash_entry *entry;
320
{
321
  struct sec_merge_sec_info *secinfo = entry->secinfo;
322
  asection *sec = secinfo->sec;
323
  char *pad = "";
324
  bfd_size_type off = 0;
325
  int alignment_power = bfd_get_section_alignment (abfd, sec->output_section);
326
 
327
  if (alignment_power)
328
    pad = bfd_zmalloc ((bfd_size_type) 1 << alignment_power);
329
 
330
  for (; entry != NULL && entry->secinfo == secinfo; entry = entry->next)
331
    {
332
      register const char *str;
333
      register size_t len;
334
 
335
      len = off & (entry->alignment - 1);
336
      if (len)
337
        {
338
          len = entry->alignment - len;
339
          if (bfd_bwrite ((PTR) pad, (bfd_size_type) len, abfd) != len)
340
            break;
341
          off += len;
342
        }
343
 
344
      str = entry->root.string;
345
      len = entry->len;
346
 
347
      if (bfd_bwrite ((PTR) str, (bfd_size_type) len, abfd) != len)
348
        break;
349
 
350
      off += len;
351
    }
352
 
353
  if (alignment_power)
354
    free (pad);
355
 
356
  return entry == NULL || entry->secinfo != secinfo;
357
}
358
 
359
/* This function is called for each input file from the add_symbols
360
   pass of the linker.  */
361
 
362
boolean
363
_bfd_merge_section (abfd, psinfo, sec, psecinfo)
364
     bfd *abfd;
365
     PTR *psinfo;
366
     asection *sec;
367
     PTR *psecinfo;
368
{
369
  struct sec_merge_info *sinfo;
370
  struct sec_merge_sec_info *secinfo;
371
  unsigned int align;
372
  bfd_size_type amt;
373
 
374
  if (sec->_raw_size == 0
375
      || (sec->flags & SEC_EXCLUDE)
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
  align = bfd_get_section_alignment (sec->owner, sec);
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))))
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
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.  */
399
      return true;
400
    }
401
 
402
  for (sinfo = (struct sec_merge_info *) *psinfo; sinfo; sinfo = sinfo->next)
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))
407
      break;
408
 
409
  if (sinfo == NULL)
410
    {
411
      /* Initialize the information we need to keep track of.  */
412
      amt = sizeof (struct sec_merge_info);
413
      sinfo = (struct sec_merge_info *) bfd_alloc (abfd, amt);
414
      if (sinfo == NULL)
415
        goto error_return;
416
      sinfo->next = (struct sec_merge_info *) *psinfo;
417
      sinfo->chain = NULL;
418
      *psinfo = (PTR) sinfo;
419
      sinfo->htab = sec_merge_init (sec->entsize, (sec->flags & SEC_STRINGS));
420
      if (sinfo->htab == NULL)
421
        goto error_return;
422
    }
423
 
424
  /* Read the section from abfd.  */
425
 
426
  amt = sizeof (struct sec_merge_sec_info) + sec->_raw_size - 1;
427
  *psecinfo = bfd_alloc (abfd, amt);
428
  if (*psecinfo == NULL)
429
    goto error_return;
430
 
431
  secinfo = (struct sec_merge_sec_info *)*psecinfo;
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;
442
  secinfo->htab = sinfo->htab;
443
  secinfo->first = NULL;
444
 
445
  if (! bfd_get_section_contents (sec->owner, sec, secinfo->contents,
446
                                  (bfd_vma) 0, sec->_raw_size))
447
    goto error_return;
448
 
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
 
458
static int
459
cmplengthentry (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;
465
 
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
 
474
static int
475
last4_eq (a, b)
476
     const PTR a;
477
     const PTR b;
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
 
502
static int
503
last_eq (a, b)
504
     const PTR a;
505
     const PTR b;
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.  */
536
static boolean
537
record_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);
549
  end = secinfo->contents + sec->_raw_size;
550
  nul = false;
551
  mask = ((bfd_vma) 1 << align) - 1;
552
  if (sec->flags & SEC_STRINGS)
553
    {
554
      for (p = secinfo->contents; p < end; )
555
        {
556
          eltalign = p - secinfo->contents;
557
          eltalign = ((eltalign ^ (eltalign - 1)) + 1) >> 1;
558
          if (!eltalign || eltalign > mask)
559
            eltalign = mask + 1;
560
          entry = sec_merge_add (sinfo->htab, p, (unsigned) eltalign, secinfo);
561
          if (! entry)
562
            goto error_return;
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;
571
                      entry = sec_merge_add (sinfo->htab, "",
572
                                             (unsigned) mask + 1, secinfo);
573
                      if (! entry)
574
                        goto error_return;
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;
591
                      entry = sec_merge_add (sinfo->htab, p,
592
                                             (unsigned) mask + 1, secinfo);
593
                      if (! entry)
594
                        goto error_return;
595
                    }
596
                  p += sec->entsize;
597
                }
598
            }
599
        }
600
    }
601
  else
602
    {
603
      for (p = secinfo->contents; p < end; p += sec->entsize)
604
        {
605
          entry = sec_merge_add (sinfo->htab, p, 1, secinfo);
606
          if (! entry)
607
            goto error_return;
608
        }
609
    }
610
 
611
  return true;
612
 
613
error_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.  */
621
static void
622
merge_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;
628
  bfd_size_type size, amt;
629
 
630
  /* Now sort the strings by length, longest first.  */
631
  array = NULL;
632
  amt = sinfo->htab->size * sizeof (struct sec_merge_hash_entry *);
633
  array = (struct sec_merge_hash_entry **) bfd_malloc (amt);
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;
642
 
643
  qsort (array, (size_t) sinfo->htab->size,
644
         sizeof (struct sec_merge_hash_entry *), cmplengthentry);
645
 
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);
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
        {
670
          s = e->root.string + e->len - e->u.entsize;
671
          hash = 0;
672
          for (i = 0; i < 4 * e->u.entsize; i++)
673
            {
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;
689
            }
690
          else
691
            *p = (PTR) e;
692
        }
693
      s = e->root.string + e->len - e->u.entsize;
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;
711
        }
712
      else
713
        *p = (PTR) e;
714
    }
715
 
716
alloc_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
}
764
 
765
/* This function is called once after all SEC_MERGE sections are registered
766
   with _bfd_merge_section.  */
767
 
768
boolean
769
_bfd_merge_sections (abfd, xsinfo, remove_hook)
770
     bfd *abfd ATTRIBUTE_UNUSED;
771
     PTR xsinfo;
772
     void (*remove_hook) PARAMS((bfd *, asection *));
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)
791
          {
792
            *secinfo->psecinfo = NULL;
793
            if (remove_hook)
794
              (*remove_hook) (abfd, secinfo->sec);
795
          }
796
        else if (! record_section (sinfo, secinfo))
797
          break;
798
 
799
      if (secinfo)
800
        continue;
801
 
802
      if (sinfo->htab->first == NULL)
803
        continue;
804
 
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)
837
            secinfo->sec->_cooked_size = 0;
838
    }
839
 
840
  return true;
841
}
842
 
843
/* Write out the merged section.  */
844
 
845
boolean
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;
852
  file_ptr pos;
853
 
854
  secinfo = (struct sec_merge_sec_info *) psecinfo;
855
 
856
  if (!secinfo->first)
857
    return true;
858
 
859
  pos = sec->output_section->filepos + sec->output_offset;
860
  if (bfd_seek (output_bfd, pos, SEEK_SET) != 0)
861
    return false;
862
 
863
  if (! sec_merge_emit (output_bfd, secinfo->first))
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
 
873
bfd_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)
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
        }
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;
903
          while (p >= secinfo->contents && *p)
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
    }
931
  entry = sec_merge_hash_lookup (secinfo->htab, p, 0, false);
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
 
948
  *psec = entry->secinfo->sec;
949
  return entry->u.index + (secinfo->contents + offset - p);
950
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.