Coverage Report

Created: 2026-03-10 08:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/binutils-gdb/bfd/merge.c
Line
Count
Source
1
/* SEC_MERGE support.
2
   Copyright (C) 2001-2026 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
20
   MA 02110-1301, USA.  */
21
22
23
/* This file contains support for merging duplicate entities within sections,
24
   as used in ELF SHF_MERGE.  */
25
26
#include "sysdep.h"
27
#include <limits.h>
28
#include "bfd.h"
29
#include "elf-bfd.h"
30
#include "libbfd.h"
31
#include "objalloc.h"
32
#include "libiberty.h"
33
34
/* We partition all mergable input sections into sets of similar
35
   characteristics.  These sets are the unit of merging.  All content
36
   of the input sections is scanned and inserted into a hash table.
37
   We also remember an input-offset to entry mapping per input section, but
38
   the content itself is removed.  After everything is read in we assign
39
   output offsets to all hash entries, and when relocations are processed we
40
   lookup the given input offset per input-section, get the matching entry
41
   and its output offset (possibly adjusted for offset pointing into the
42
   middle of an entry).
43
44
   The input-offset-to-entry mapping (in map_ofs/map) is sorted, so in principle
45
   we could binary search it, but that's not cache-friendly and it's faster
46
   to add another lookup structure that gets us very near the correct
47
   entry in just one step (that's what ofstolowbound is for) and do a linear
48
   search from there.  */
49
50
/* An entry in the section merge hash table.  */
51
52
struct sec_merge_hash_entry
53
{
54
  /* Length of this entry.  This includes the zero terminator.  */
55
  unsigned int len;
56
  /* Start of this string needs to be aligned to
57
     alignment octets (not 1 << align).  */
58
  unsigned int alignment;
59
  union
60
  {
61
    /* Index within the merged section.  */
62
    bfd_size_type index;
63
    /* Entry this is a suffix of (if alignment is 0).  */
64
    struct sec_merge_hash_entry *suffix;
65
  } u;
66
  /* Next entity in the hash table (in order of entering).  */
67
  struct sec_merge_hash_entry *next;
68
  char str[1];
69
};
70
71
/* The section merge hash table.  */
72
73
struct sec_merge_hash
74
{
75
  struct bfd_hash_table table;
76
  /* First entity in the SEC_MERGE sections of this type.  */
77
  struct sec_merge_hash_entry *first;
78
  /* Last entity in the SEC_MERGE sections of this type.  */
79
  struct sec_merge_hash_entry *last;
80
  /* Entity size.  */
81
  unsigned int entsize;
82
  /* Are entries fixed size or zero terminated strings?  */
83
  bool strings;
84
  /* struct-of-array variant of all entries in the hash-table: */
85
  unsigned int nbuckets;
86
  /* We keep hash-code and length of entry together in a separate
87
     array in such a way that it can be checked with just a single memory
88
     reference.  In this way we don't need indirect access to the entries
89
     in the normal case.  keys_lens[i] is 'hashcode << 32) | len' for entry
90
     i (which is pointed to be values[i]).  */
91
  uint64_t *key_lens;
92
  struct sec_merge_hash_entry **values;
93
};
94
95
struct sec_merge_sec_info;
96
97
/* Information per merged blob.  This is the unit of merging and is
98
   related to (multiple) input sections of similar characteristics
99
   (alignment, entity size, strings or blobs).  */
100
struct sec_merge_info
101
{
102
  /* Chain of sec_merge_infos.  */
103
  struct sec_merge_info *next;
104
  /* Chain of sec_merge_sec_infos.  This first one will be the representative
105
     section that conceptually collects all merged content.  */
106
  struct sec_merge_sec_info *chain;
107
  struct sec_merge_sec_info **last;
108
  /* A hash table used to hold section content.  */
109
  struct sec_merge_hash *htab;
110
};
111
112
/* Offset into input mergable sections are represented by this type.
113
   Note how doesn't support crazy large mergable sections.  */
114
typedef uint32_t mapofs_type;
115
116
/* Given a sec_merge_sec_info S this gives the input offset of the IDX's
117
   recorded entry.  */
118
0
#define MAP_OFS(S,IDX) (S)->map_ofs[IDX]
119
/* And this gives the output offset (in the merged blob representing
120
   this S.  */
121
0
#define MAP_IDX(S,IDX) (S)->map[IDX].idx
122
/* For quick lookup of output offset given an input offset we store
123
   an array mapping intput-offset / OFSDIV to entry index.
124
   16 is better than 8, 32 is roughly same as 16, but uses less memory, so
125
   we use that. */
126
0
#define OFSDIV 32
127
128
/* Information per input merge section.  */
129
struct sec_merge_sec_info
130
{
131
  /* Chain of sec_merge_sec_infos.  */
132
  struct sec_merge_sec_info *next;
133
  /* The corresponding section.  */
134
  asection *sec;
135
  /* The merge entity this is a part of.  */
136
  struct sec_merge_info *sinfo;
137
  /* The section associated with sinfo (i.e. the representative section).
138
     Same as sinfo->chain->sec, but faster to access in the hot function.  */
139
  asection *reprsec;
140
  /* First string in this section.  */
141
  struct sec_merge_hash_entry *first_str;
142
  /* Sparse mapping from input offset to entry covering that offset:  */
143
  unsigned int noffsetmap;  /* Number of these mappings.  */
144
  mapofs_type *map_ofs;     /* Input offset.  */
145
  union {
146
      struct sec_merge_hash_entry *entry;  /* Covering hash entry ... */
147
      bfd_size_type idx;                   /* ... or destination offset.  */
148
  } *map;
149
  /* Quick access: index into map_ofs[].  ofstolowbound[o / OFSDIV]=I is
150
     such that map_ofs[I] is the smallest offset higher that
151
     rounddown(o, OFSDIV) (and hence I-1 is the largest entry whose offset is
152
     smaller or equal to o/OFSDIV*OFSDIV).  */
153
  unsigned int *ofstolowbound;
154
  int fast_state;
155
};
156
157
158
/* True when COUNT+ADDED and NBUCKETS indicate that the hash table
159
   needs resizing.  */
160
161
static inline bool
162
needs_resize (unsigned int count, unsigned int added, unsigned int nbuckets)
163
0
{
164
  /* This doesn't consider the possibility of "count" + "added"
165
     overflowing, because that can't happen given current usage.  If
166
     code calling this function changes then that assumption may no
167
     longer be correct.  Currently "added" is always 1 and "nbuckets"
168
     is limited to 0x80000000.  We'll attempt and fail resizing at
169
     "count" of 0x55555555.  */
170
0
  return count + added > nbuckets / 3 * 2;
171
0
}
172
173
/* Given a merge hash table TABLE and a number of entries to be
174
   ADDED, resize the table for this to fit.
175
   Returns false if that can't be done for whatever reason.  */
176
177
static bool
178
sec_merge_resize (struct sec_merge_hash *table, unsigned added)
179
0
{
180
0
  struct bfd_hash_table *bfdtab = &table->table;
181
0
  unsigned i;
182
0
  unsigned long newnb = table->nbuckets;
183
0
  struct sec_merge_hash_entry **newv;
184
0
  uint64_t *newl;
185
0
  unsigned long alloc;
186
187
0
  do
188
0
    {
189
0
      if (newnb >> (8 * sizeof(mapofs_type) - 1))
190
0
  return false;
191
0
      newnb *= 2;
192
0
    }
193
0
  while (needs_resize (bfdtab->count, added, newnb));
194
195
0
  alloc = newnb * sizeof (newl[0]);
196
0
  if (alloc / sizeof (newl[0]) != newnb)
197
0
    return false;
198
0
  newl = objalloc_alloc ((struct objalloc *) table->table.memory, alloc);
199
0
  if (newl == NULL)
200
0
    return false;
201
0
  memset (newl, 0, alloc);
202
0
  alloc = newnb * sizeof (newv[0]);
203
0
  if (alloc / sizeof (newv[0]) != newnb)
204
0
    return false;
205
0
  newv = objalloc_alloc ((struct objalloc *) table->table.memory, alloc);
206
0
  if (newv == NULL)
207
0
    return false;
208
0
  memset (newv, 0, alloc);
209
210
0
  for (i = 0; i < table->nbuckets; i++)
211
0
    {
212
0
      struct sec_merge_hash_entry *v = table->values[i];
213
0
      if (v)
214
0
  {
215
0
    uint32_t thishash = table->key_lens[i] >> 32;
216
0
    unsigned idx = thishash & (newnb - 1);
217
0
    while (newv[idx])
218
0
      idx = (idx + 1) & (newnb - 1);
219
0
    newl[idx] = table->key_lens[i];
220
0
    newv[idx] = v;
221
0
  }
222
0
    }
223
224
0
  table->key_lens = newl;
225
0
  table->values = newv;
226
0
  table->nbuckets = newnb;
227
0
  return true;
228
0
}
229
230
/* Insert STRING (actually a byte blob of length LEN, with pre-computed
231
   HASH and bucket _INDEX) into our hash TABLE.  */
232
233
static struct sec_merge_hash_entry *
234
sec_merge_hash_insert (struct sec_merge_hash *table,
235
     const char *string,
236
     uint64_t hash, unsigned int len, unsigned int _index)
237
0
{
238
0
  struct bfd_hash_table *bfdtab = &table->table;
239
0
  struct sec_merge_hash_entry *hashp;
240
241
0
  hashp = (struct sec_merge_hash_entry *)
242
0
      bfd_hash_allocate (bfdtab, len + sizeof (struct sec_merge_hash_entry));
243
0
  if (hashp == NULL)
244
0
    return NULL;
245
246
0
  memcpy (hashp->str, string, len);
247
0
  hashp->len = len;
248
0
  hashp->alignment = 0;
249
0
  hashp->u.suffix = NULL;
250
0
  hashp->next = NULL;
251
252
0
  if (needs_resize (bfdtab->count, 1, table->nbuckets))
253
0
    {
254
0
      if (!sec_merge_resize (table, 1))
255
0
  return NULL;
256
0
      uint64_t *key_lens = table->key_lens;
257
0
      unsigned int nbuckets = table->nbuckets;
258
0
      _index = hash & (nbuckets - 1);
259
0
      while (1)
260
0
  {
261
0
    uint64_t candlen = key_lens[_index];
262
0
    if (!(candlen & (uint32_t)-1))
263
0
      break;
264
0
    _index = (_index + 1) & (nbuckets - 1);
265
0
  }
266
0
    }
267
268
0
  bfdtab->count++;
269
0
  table->key_lens[_index] = (hash << 32) | (uint32_t)len;
270
0
  table->values[_index] = hashp;
271
272
0
  return hashp;
273
0
}
274
275
/* Read four bytes from *STR, interpret it as 32bit unsigned little
276
   endian value and return that.  */
277
278
static inline uint32_t
279
hash_read32 (const char *str)
280
0
{
281
0
  uint32_t i;
282
  /* All reasonable compilers will inline this memcpy and generate optimal
283
     code on architectures that support unaligned (4-byte) accesses.  */
284
0
  memcpy(&i, str, 4);
285
#ifdef WORDS_BIGENDIAN
286
  i = (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24);
287
#endif
288
0
  return i;
289
0
}
290
291
/* Calculate and return a hashvalue of the bytes at STR[0..LEN-1].
292
   All non-zero lengths and all alignments are supported.
293
294
   This is somewhat similar to xxh3 (of xxhash), but restricted to 32bit.
295
   On cc1 strings this has quite similar statistic properties, and we
296
   don't need to jump through hoops to get fast 64x64->128 mults,
297
   or 64bit arith on 32 bit hosts.  We also don't care for seeds
298
   or secrets.  They improve mixing very little.  */
299
300
static uint32_t
301
hash_blob (const char *str, unsigned int len)
302
0
{
303
0
  uint32_t ret = 0;
304
0
  uint32_t mul = (1 << 0) +  (1 << 2) + (1 << 3) + (1 << 5) + (1 << 7);
305
0
  mul += (1 << 11) + (1 << 13) + (1 << 17) + (0 << 19) + (1 << 23) + (1 << 29);
306
0
  mul += (1u << 31);
307
0
  if (len >= 8)
308
0
    {
309
0
      uint32_t acc = len * 0x9e3779b1;
310
0
      while (len >= 8)
311
0
  {
312
0
    uint32_t i1 = hash_read32  (str) ^ (0x396cfeb8 + 1*len);
313
0
    uint32_t i2 = hash_read32  (str + 4) ^ (0xbe4ba423 + 1*len);
314
0
    str += 8;
315
0
    len -= 8;
316
0
    uint64_t m = (uint64_t)i1 * i2;
317
0
    acc += (uint32_t)m ^ (uint32_t)(m >> 32);
318
0
  }
319
0
      acc = acc ^ (acc >> 7);
320
0
      uint64_t r = (uint64_t)mul * acc;
321
0
      ret = (uint32_t)r ^ (uint32_t)(r >> 32);
322
0
      if (len == 0)
323
0
  goto end;
324
0
    }
325
0
  if (len >= 4)
326
0
    {
327
0
      uint32_t i1 = hash_read32  (str);
328
0
      uint32_t i2 = hash_read32  (str + len - 4);
329
0
      i1 = ((i1 + len) ^ (i1 >> 7));
330
0
      i2 = i2 ^ (i2 >> 7);
331
0
      uint64_t r = (uint64_t)mul * i1 + i2;
332
0
      ret += r ^ (r >> 32);
333
0
    }
334
0
  else
335
0
    {
336
      /* Cleverly read in 1 to 3 bytes without further conditionals.  */
337
0
      unsigned char c1 = str[0];
338
0
      unsigned char c2 = str[len >> 1];
339
0
      unsigned char c3 = str[len - 1];
340
0
      uint32_t i1 = ((uint32_t)c1 << 16) | ((uint32_t)c2 << 24)
341
0
         | ((uint32_t) c3) | (len << 8);
342
0
      i1 = i1 ^ (i1 >> 7);
343
0
      uint64_t r = (uint64_t)mul * i1;
344
0
      ret += r ^ (r >> 32);
345
0
    }
346
0
end:
347
0
  return ret;
348
0
}
349
350
/* Given a hash TABLE, return the hash of STRING (a blob described
351
   according to info in TABLE, either a character string, or some fixed
352
   size entity) and set *PLEN to the length of this blob.  */
353
354
static uint32_t
355
hashit (struct sec_merge_hash *table, const char *string, unsigned int *plen)
356
0
{
357
0
  const unsigned char *s;
358
0
  uint32_t hash;
359
0
  unsigned int len, i;
360
361
0
  s = (const unsigned char *) string;
362
0
  if (table->strings)
363
0
    {
364
0
      if (table->entsize == 1)
365
0
  len = strlen (string) + 1;
366
0
      else
367
0
  {
368
0
    len = 0;
369
0
    for (;;)
370
0
      {
371
0
        for (i = 0; i < table->entsize; ++i)
372
0
    if (s[i] != '\0')
373
0
      break;
374
0
        if (i == table->entsize)
375
0
    break;
376
0
        s += table->entsize;
377
0
        ++len;
378
0
      }
379
0
    len *= table->entsize;
380
0
    len += table->entsize;
381
0
  }
382
0
    }
383
0
  else
384
0
    len = table->entsize;
385
0
  hash = hash_blob (string, len);
386
0
  *plen = len;
387
0
  return hash;
388
0
}
389
390
/* Lookup or insert a blob STRING (of length LEN, precomputed HASH and
391
   input ALIGNMENT) into TABLE.  Return the found or new hash table entry.  */
392
393
static struct sec_merge_hash_entry *
394
sec_merge_hash_lookup (struct sec_merge_hash *table, const char *string,
395
           unsigned int len, uint64_t hash,
396
           unsigned int alignment)
397
0
{
398
0
  struct sec_merge_hash_entry *hashp;
399
0
  unsigned int _index;
400
401
  /*printf ("YYY insert 0x%x into %u buckets (%s)\n",
402
    (unsigned)hash, (unsigned)table->nbuckets, string);*/
403
0
  uint64_t *key_lens = table->key_lens;
404
0
  struct sec_merge_hash_entry **values = table->values;
405
0
  uint64_t hlen = (hash << 32) | (uint32_t)len;
406
0
  unsigned int nbuckets = table->nbuckets;
407
0
  _index = hash & (nbuckets - 1);
408
0
  while (1)
409
0
    {
410
0
      uint64_t candlen = key_lens[_index];
411
0
      if (candlen == hlen
412
0
    && !memcmp (values[_index]->str, string, len))
413
0
  {
414
0
    hashp = values[_index];
415
0
    if (hashp->alignment < alignment)
416
0
      hashp->alignment = alignment;
417
0
    return hashp;
418
0
  }
419
0
      if (!(candlen & (uint32_t)-1))
420
0
  break;
421
0
      _index = (_index + 1) & (nbuckets - 1);
422
0
    }
423
424
0
  hashp = sec_merge_hash_insert (table, string, hash, len, _index);
425
0
  if (hashp == NULL)
426
0
    return NULL;
427
0
  hashp->alignment = alignment;
428
429
0
  if (table->first == NULL)
430
0
    table->first = hashp;
431
0
  else
432
0
    table->last->next = hashp;
433
0
  table->last = hashp;
434
435
0
  return hashp;
436
0
}
437
438
/* Create a new hash table.  */
439
440
static struct sec_merge_hash *
441
sec_merge_init (unsigned int entsize, bool strings)
442
0
{
443
0
  struct sec_merge_hash *table;
444
445
0
  table = (struct sec_merge_hash *) bfd_malloc (sizeof (struct sec_merge_hash));
446
0
  if (table == NULL)
447
0
    return NULL;
448
449
0
  if (! bfd_hash_table_init_n (&table->table, NULL,
450
0
             sizeof (struct sec_merge_hash_entry), 0x2000))
451
0
    {
452
0
      free (table);
453
0
      return NULL;
454
0
    }
455
456
0
  table->first = NULL;
457
0
  table->last = NULL;
458
0
  table->entsize = entsize;
459
0
  table->strings = strings;
460
461
0
  table->nbuckets = 0x2000;
462
0
  table->key_lens = objalloc_alloc ((struct objalloc *) table->table.memory,
463
0
        table->nbuckets * sizeof (table->key_lens[0]));
464
0
  memset (table->key_lens, 0, table->nbuckets * sizeof (table->key_lens[0]));
465
0
  table->values = objalloc_alloc ((struct objalloc *) table->table.memory,
466
0
        table->nbuckets * sizeof (table->values[0]));
467
0
  memset (table->values, 0, table->nbuckets * sizeof (table->values[0]));
468
469
0
  return table;
470
0
}
471
472
/* Append the tuple of input-offset O corresponding
473
   to hash table ENTRY into SECINFO, such that we later may lookup the
474
   entry just by O.  */
475
476
static bool
477
append_offsetmap (struct sec_merge_sec_info *secinfo,
478
      mapofs_type o,
479
      struct sec_merge_hash_entry *entry)
480
0
{
481
0
  if ((secinfo->noffsetmap & 2047) == 0)
482
0
    {
483
0
      bfd_size_type amt;
484
0
      amt = (secinfo->noffsetmap + 2048);
485
0
      secinfo->map_ofs = bfd_realloc (secinfo->map_ofs,
486
0
              amt * sizeof(secinfo->map_ofs[0]));
487
0
      if (!secinfo->map_ofs)
488
0
  return false;
489
0
      secinfo->map = bfd_realloc (secinfo->map, amt * sizeof(secinfo->map[0]));
490
0
      if (!secinfo->map)
491
0
  return false;
492
0
    }
493
0
  unsigned int i = secinfo->noffsetmap++;
494
0
  MAP_OFS(secinfo, i) = o;
495
0
  secinfo->map[i].entry = entry;
496
0
  return true;
497
0
}
498
499
/* Prepare the input-offset-to-entry tables after output offsets are
500
   determined.  */
501
502
static void
503
prepare_offsetmap (struct sec_merge_sec_info *secinfo)
504
0
{
505
0
  unsigned int noffsetmap = secinfo->noffsetmap;
506
0
  unsigned int i, lbi;
507
0
  bfd_size_type l, sz, amt;
508
509
0
  secinfo->fast_state = 1;
510
511
0
  for (i = 0; i < noffsetmap; i++)
512
0
    MAP_IDX(secinfo, i) = secinfo->map[i].entry->u.index;
513
514
0
  sz = secinfo->sec->rawsize;
515
0
  amt = (sz / OFSDIV + 1) * sizeof (secinfo->ofstolowbound[0]);
516
0
  secinfo->ofstolowbound = bfd_zmalloc (amt);
517
0
  if (!secinfo->ofstolowbound)
518
0
    return;
519
0
  for (l = lbi = 0; l < sz; l += OFSDIV)
520
0
    {
521
      /* No need for bounds checking on lbi, as we've added a sentinel that's
522
   larger than any offset.  */
523
0
      while (MAP_OFS(secinfo, lbi) <= l)
524
0
  lbi++;
525
      //BFD_ASSERT ((l / OFSDIV) <= (i / OFSDIV));
526
0
      secinfo->ofstolowbound[l / OFSDIV] = lbi;
527
0
    }
528
0
  secinfo->fast_state = 2;
529
0
}
530
531
static bool
532
sec_merge_emit (bfd *abfd, struct sec_merge_sec_info *secinfo,
533
    unsigned char *contents)
534
0
{
535
0
  struct sec_merge_hash_entry *entry = secinfo->first_str;
536
0
  asection *sec = secinfo->sec;
537
0
  file_ptr offset = sec->output_offset;
538
0
  char *pad = NULL;
539
0
  bfd_size_type off = 0;
540
0
  unsigned int opb = bfd_octets_per_byte (abfd, sec);
541
0
  int alignment_power = sec->output_section->alignment_power * opb;
542
0
  bfd_size_type pad_len;  /* Octets.  */
543
544
  /* FIXME: If alignment_power is 0 then really we should scan the
545
     entry list for the largest required alignment and use that.  */
546
0
  pad_len = alignment_power ? ((bfd_size_type) 1 << alignment_power) : 16;
547
548
0
  pad = (char *) bfd_zmalloc (pad_len);
549
0
  if (pad == NULL)
550
0
    return false;
551
552
0
  for (; entry != NULL; entry = entry->next)
553
0
    {
554
0
      const char *str;
555
0
      bfd_size_type len;
556
557
0
      if (!entry->len)
558
0
  continue;
559
0
      BFD_ASSERT (entry->alignment);
560
0
      len = -off & (entry->alignment - 1);
561
0
      if (len != 0)
562
0
  {
563
0
    BFD_ASSERT (len <= pad_len);
564
0
    if (contents)
565
0
      {
566
0
        memcpy (contents + offset, pad, len);
567
0
        offset += len;
568
0
      }
569
0
    else if (bfd_write (pad, len, abfd) != len)
570
0
      goto err;
571
0
    off += len;
572
0
  }
573
574
0
      str = entry->str;
575
0
      len = entry->len;
576
577
0
      if (contents)
578
0
  {
579
0
    memcpy (contents + offset, str, len);
580
0
    offset += len;
581
0
  }
582
0
      else if (bfd_write (str, len, abfd) != len)
583
0
  goto err;
584
585
0
      off += len;
586
0
    }
587
0
  BFD_ASSERT (!entry);
588
589
  /* Trailing alignment needed?  */
590
0
  off = sec->size - off;
591
0
  if (1 && off != 0)
592
0
    {
593
0
      BFD_ASSERT (off <= pad_len);
594
0
      if (contents)
595
0
  memcpy (contents + offset, pad, off);
596
0
      else if (bfd_write (pad, off, abfd) != off)
597
0
  goto err;
598
0
    }
599
600
0
  free (pad);
601
0
  return true;
602
603
0
 err:
604
0
  free (pad);
605
0
  return false;
606
0
}
607
608
/* Register a SEC_MERGE section as a candidate for merging.
609
   This function is called for all non-dynamic SEC_MERGE input sections.  */
610
611
static bool
612
_bfd_add_merge_section (bfd *abfd, void **psinfo, asection *sec)
613
0
{
614
0
  struct sec_merge_info *sinfo;
615
0
  struct sec_merge_sec_info *secinfo;
616
0
  asection *repr;
617
0
  unsigned int alignment_power;  /* Octets.  */
618
0
  unsigned int align;            /* Octets.  */
619
0
  unsigned int opb = bfd_octets_per_byte (abfd, sec);
620
621
0
  if ((abfd->flags & DYNAMIC) != 0
622
0
      || (sec->flags & SEC_MERGE) == 0)
623
0
    abort ();
624
625
0
  if (sec->size == 0
626
0
      || (sec->flags & SEC_EXCLUDE) != 0
627
0
      || (sec->flags & SEC_HAS_CONTENTS) == 0
628
0
      || sec->entsize == 0)
629
0
    return true;
630
631
0
  if (sec->size % sec->entsize != 0)
632
0
    return true;
633
634
0
  if ((sec->flags & SEC_RELOC) != 0)
635
0
    {
636
      /* We aren't prepared to handle relocations in merged sections.  */
637
0
      return true;
638
0
    }
639
640
0
  if (sec->size > (mapofs_type)-1)
641
0
    {
642
      /* Input offsets must be representable by mapofs_type.  */
643
0
      return true;
644
0
    }
645
646
#ifndef CHAR_BIT
647
#define CHAR_BIT 8
648
#endif
649
0
  alignment_power = sec->alignment_power * opb;
650
0
  if (alignment_power >= sizeof (align) * CHAR_BIT)
651
0
    return true;
652
653
0
  align = 1u << alignment_power;
654
0
  if ((sec->entsize < align
655
0
       && ((sec->entsize & (sec->entsize - 1))
656
0
     || !(sec->flags & SEC_STRINGS)))
657
0
      || (sec->entsize > align
658
0
    && (sec->entsize & (align - 1))))
659
0
    {
660
      /* Sanity check.  If string character size is smaller than
661
   alignment, then we require character size to be a power
662
   of 2, otherwise character size must be integer multiple
663
   of alignment.  For non-string constants, alignment must
664
   be smaller than or equal to entity size and entity size
665
   must be integer multiple of alignment.  */
666
0
      return true;
667
0
    }
668
669
  /* Initialize the descriptor for this input section.  */
670
671
0
  sec->sec_info = secinfo = bfd_zalloc (abfd, sizeof (*secinfo));
672
0
  if (sec->sec_info == NULL)
673
0
    goto error_return;
674
675
0
  secinfo->sec = sec;
676
677
  /* Search for a matching output merged section.  */
678
0
  for (sinfo = (struct sec_merge_info *) *psinfo; sinfo; sinfo = sinfo->next)
679
0
    if (sinfo->chain
680
0
  && (repr = sinfo->chain->sec)
681
0
  && ! ((repr->flags ^ sec->flags) & (SEC_MERGE | SEC_STRINGS))
682
0
  && repr->entsize == sec->entsize
683
0
  && repr->alignment_power == sec->alignment_power
684
0
  && repr->output_section == sec->output_section)
685
0
      break;
686
687
0
  if (sinfo == NULL)
688
0
    {
689
      /* Initialize the information we need to keep track of.  */
690
0
      sinfo = (struct sec_merge_info *)
691
0
    bfd_alloc (abfd, sizeof (struct sec_merge_info));
692
0
      if (sinfo == NULL)
693
0
  goto error_return;
694
0
      sinfo->next = (struct sec_merge_info *) *psinfo;
695
0
      sinfo->chain = NULL;
696
0
      sinfo->last = &sinfo->chain;
697
0
      *psinfo = sinfo;
698
0
      sinfo->htab = sec_merge_init (sec->entsize, (sec->flags & SEC_STRINGS));
699
0
      if (sinfo->htab == NULL)
700
0
  goto error_return;
701
0
    }
702
703
0
  *sinfo->last = secinfo;
704
0
  sinfo->last = &secinfo->next;
705
706
0
  secinfo->sinfo = sinfo;
707
0
  secinfo->reprsec = sinfo->chain->sec;
708
709
0
  sec->sec_info_type = SEC_INFO_TYPE_MERGE;
710
711
0
  return true;
712
713
0
 error_return:
714
0
  sec->sec_info = NULL;
715
0
  return false;
716
0
}
717
718
/* Record one whole input section (described by SECINFO) into the hash table
719
   SINFO.  Returns true when section is completely recorded, and false when
720
   it wasn't recorded but we can continue (e.g. by simply not deduplicating
721
   this section).  */
722
723
static bool
724
record_section (struct sec_merge_info *sinfo,
725
    struct sec_merge_sec_info *secinfo)
726
0
{
727
0
  asection *sec = secinfo->sec;
728
0
  struct sec_merge_hash_entry *entry;
729
0
  unsigned char *p, *end;
730
0
  bfd_vma mask, eltalign;
731
0
  unsigned int align;
732
0
  bfd_size_type amt;
733
0
  bfd_byte *contents;
734
0
  void *tmpptr;
735
736
0
  amt = sec->size;
737
0
  if (sec->flags & SEC_STRINGS)
738
    /* Some versions of gcc may emit a string without a zero terminator.
739
       See http://gcc.gnu.org/ml/gcc-patches/2006-06/msg01004.html
740
       Allocate space for an extra zero.  */
741
0
    amt += sec->entsize;
742
0
  contents = bfd_malloc (amt);
743
0
  if (!contents)
744
0
    goto error_return;
745
746
  /* Slurp in all section contents (possibly decompressing it).  */
747
0
  sec->rawsize = sec->size;
748
0
  if (sec->flags & SEC_STRINGS)
749
0
    memset (contents + sec->size, 0, sec->entsize);
750
0
  if (! bfd_get_full_section_contents (sec->owner, sec, &contents))
751
0
    goto error_return;
752
753
  /* Now populate the hash table and offset mapping.  */
754
755
  /* Walk through the contents, calculate hashes and length of all
756
     blobs (strings or fixed-size entries) we find and fill the
757
     hash and offset tables.  */
758
0
  align = sec->alignment_power;
759
0
  mask = ((bfd_vma) 1 << align) - 1;
760
0
  end = contents + sec->size;
761
0
  for (p = contents; p < end;)
762
0
    {
763
0
      unsigned len;
764
0
      uint32_t hash = hashit (sinfo->htab, (char*) p, &len);
765
0
      unsigned int ofs = p - contents;
766
0
      eltalign = ofs;
767
0
      eltalign = ((eltalign ^ (eltalign - 1)) + 1) >> 1;
768
0
      if (!eltalign || eltalign > mask)
769
0
  eltalign = mask + 1;
770
0
      entry = sec_merge_hash_lookup (sinfo->htab, (char *) p, len, hash,
771
0
             (unsigned) eltalign);
772
0
      if (! entry)
773
0
  goto error_return;
774
0
      if (! append_offsetmap (secinfo, ofs, entry))
775
0
  goto error_return;
776
0
      p += len;
777
0
    }
778
779
  /* Add a sentinel element that's conceptually behind all others.  */
780
0
  append_offsetmap (secinfo, sec->size, NULL);
781
  /* But don't count it.  */
782
0
  secinfo->noffsetmap--;
783
784
0
  free (contents);
785
0
  contents = NULL;
786
787
  /* We allocate the ofsmap arrays in blocks of 2048 elements.
788
     In case we have very many small input files/sections,
789
     this might waste large amounts of memory, so reallocate these
790
     arrays here to their true size.  */
791
0
  amt = secinfo->noffsetmap + 1;
792
0
  tmpptr = bfd_realloc (secinfo->map, amt * sizeof(secinfo->map[0]));
793
0
  if (tmpptr)
794
0
    secinfo->map = tmpptr;
795
0
  tmpptr = bfd_realloc (secinfo->map_ofs, amt * sizeof(secinfo->map_ofs[0]));
796
0
  if (tmpptr)
797
0
    secinfo->map_ofs = tmpptr;
798
799
  /*printf ("ZZZ %s:%s %u entries\n", sec->owner->filename, sec->name,
800
    (unsigned)secinfo->noffsetmap);*/
801
802
0
  return true;
803
804
0
 error_return:
805
0
  free (contents);
806
0
  contents = NULL;
807
0
  return false;
808
0
}
809
810
/* qsort comparison function.  Won't ever return zero as all entries
811
   differ, so there is no issue with qsort stability here.  */
812
813
static int
814
strrevcmp (const void *a, const void *b)
815
0
{
816
0
  struct sec_merge_hash_entry *A = *(struct sec_merge_hash_entry **) a;
817
0
  struct sec_merge_hash_entry *B = *(struct sec_merge_hash_entry **) b;
818
0
  unsigned int lenA = A->len;
819
0
  unsigned int lenB = B->len;
820
0
  const unsigned char *s = (const unsigned char *) A->str + lenA - 1;
821
0
  const unsigned char *t = (const unsigned char *) B->str + lenB - 1;
822
0
  int l = lenA < lenB ? lenA : lenB;
823
824
0
  while (l)
825
0
    {
826
0
      if (*s != *t)
827
0
  return (int) *s - (int) *t;
828
0
      s--;
829
0
      t--;
830
0
      l--;
831
0
    }
832
0
  return lenA - lenB;
833
0
}
834
835
/* Like strrevcmp, but for the case where all strings have the same
836
   alignment > entsize.  */
837
838
static int
839
strrevcmp_align (const void *a, const void *b)
840
0
{
841
0
  struct sec_merge_hash_entry *A = *(struct sec_merge_hash_entry **) a;
842
0
  struct sec_merge_hash_entry *B = *(struct sec_merge_hash_entry **) b;
843
0
  unsigned int lenA = A->len;
844
0
  unsigned int lenB = B->len;
845
0
  const unsigned char *s = (const unsigned char *) A->str + lenA - 1;
846
0
  const unsigned char *t = (const unsigned char *) B->str + lenB - 1;
847
0
  int l = lenA < lenB ? lenA : lenB;
848
0
  int tail_align = (lenA & (A->alignment - 1)) - (lenB & (A->alignment - 1));
849
850
0
  if (tail_align != 0)
851
0
    return tail_align;
852
853
0
  while (l)
854
0
    {
855
0
      if (*s != *t)
856
0
  return (int) *s - (int) *t;
857
0
      s--;
858
0
      t--;
859
0
      l--;
860
0
    }
861
0
  return lenA - lenB;
862
0
}
863
864
static inline int
865
is_suffix (const struct sec_merge_hash_entry *A,
866
     const struct sec_merge_hash_entry *B)
867
0
{
868
0
  if (A->len <= B->len)
869
    /* B cannot be a suffix of A unless A is equal to B, which is guaranteed
870
       not to be equal by the hash table.  */
871
0
    return 0;
872
873
0
  return memcmp (A->str + (A->len - B->len),
874
0
     B->str, B->len) == 0;
875
0
}
876
877
/* This is a helper function for bfd_merge_sections.  It attempts to
878
   merge strings matching suffixes of longer strings.  */
879
static struct sec_merge_sec_info *
880
merge_strings (struct sec_merge_info *sinfo)
881
0
{
882
0
  struct sec_merge_hash_entry **array, **a, *e;
883
0
  struct sec_merge_sec_info *secinfo;
884
0
  bfd_size_type size, amt;
885
0
  unsigned int alignment = 0;
886
887
  /* Now sort the strings */
888
0
  amt = sinfo->htab->table.count * sizeof (struct sec_merge_hash_entry *);
889
0
  array = (struct sec_merge_hash_entry **) bfd_malloc (amt);
890
0
  if (array == NULL)
891
0
    return NULL;
892
893
0
  for (e = sinfo->htab->first, a = array; e; e = e->next)
894
0
    if (e->alignment)
895
0
      {
896
0
  *a++ = e;
897
  /* Adjust the length to not include the zero terminator.  */
898
0
  e->len -= sinfo->htab->entsize;
899
0
  if (alignment != e->alignment)
900
0
    {
901
0
      if (alignment == 0)
902
0
        alignment = e->alignment;
903
0
      else
904
0
        alignment = (unsigned) -1;
905
0
    }
906
0
      }
907
908
0
  size_t asize = a - array;
909
0
  if (asize != 0)
910
0
    {
911
0
      qsort (array, asize,
912
0
       sizeof (struct sec_merge_hash_entry *),
913
0
       (alignment != (unsigned) -1 && alignment > sinfo->htab->entsize
914
0
        ? strrevcmp_align : strrevcmp));
915
916
      /* Loop over the sorted array and merge suffixes */
917
0
      e = *--a;
918
0
      e->len += sinfo->htab->entsize;
919
0
      while (--a >= array)
920
0
  {
921
0
    struct sec_merge_hash_entry *cmp = *a;
922
923
0
    cmp->len += sinfo->htab->entsize;
924
0
    if (e->alignment >= cmp->alignment
925
0
        && !((e->len - cmp->len) & (cmp->alignment - 1))
926
0
        && is_suffix (e, cmp))
927
0
      {
928
0
        cmp->u.suffix = e;
929
0
        cmp->alignment = 0;
930
0
      }
931
0
    else
932
0
      e = cmp;
933
0
  }
934
0
    }
935
936
0
  free (array);
937
938
  /* Now assign positions to the strings we want to keep.  */
939
0
  size = 0;
940
0
  secinfo = sinfo->chain;
941
0
  for (e = sinfo->htab->first; e; e = e->next)
942
0
    {
943
0
      if (e->alignment)
944
0
  {
945
0
    size = (size + e->alignment - 1) & ~((bfd_vma) e->alignment - 1);
946
0
    e->u.index = size;
947
0
    size += e->len;
948
0
  }
949
0
    }
950
0
  secinfo->sec->size = size;
951
952
  /* And now adjust the rest, removing them from the chain (but not hashtable)
953
     at the same time.  */
954
0
  for (a = &sinfo->htab->first, e = *a; e; e = e->next)
955
0
    if (e->alignment)
956
0
      a = &e->next;
957
0
    else
958
0
      {
959
0
  *a = e->next;
960
0
  if (e->len)
961
0
    {
962
0
      e->alignment = e->u.suffix->alignment;
963
0
      e->u.index = e->u.suffix->u.index + (e->u.suffix->len - e->len);
964
0
    }
965
0
      }
966
967
0
  BFD_ASSERT (!secinfo->first_str);
968
0
  secinfo->first_str = sinfo->htab->first;
969
970
0
  return secinfo;
971
0
}
972
973
/* This function is called once after all SEC_MERGE sections are registered
974
   with _bfd_merge_section.  */
975
976
static bool
977
merge_sections (bfd *abfd,
978
    struct bfd_link_info *info ATTRIBUTE_UNUSED,
979
    void *xsinfo)
980
0
{
981
0
  struct sec_merge_info *sinfo;
982
983
0
  for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next)
984
0
    {
985
0
      struct sec_merge_sec_info *secinfo;
986
0
      bfd_size_type align;  /* Bytes.  */
987
988
0
      if (! sinfo->chain)
989
0
  continue;
990
991
      /* Record the sections into the hash table.  */
992
0
      align = 1;
993
0
      for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
994
0
  if (secinfo->sec->flags & SEC_EXCLUDE
995
0
      || !record_section (sinfo, secinfo))
996
0
    {
997
0
      BFD_ASSERT (secinfo->sec->sec_info_type == SEC_INFO_TYPE_MERGE);
998
0
      secinfo->sec->sec_info = NULL;
999
0
      secinfo->sec->sec_info_type = SEC_INFO_TYPE_NONE;
1000
0
    }
1001
0
  else if (align)
1002
0
    {
1003
0
      unsigned int opb = bfd_octets_per_byte (abfd, secinfo->sec);
1004
1005
0
      align = (bfd_size_type) 1 << secinfo->sec->alignment_power;
1006
0
      if (((secinfo->sec->size / opb) & (align - 1)) != 0)
1007
0
        align = 0;
1008
0
    }
1009
1010
0
      if (sinfo->htab->first == NULL)
1011
0
  continue;
1012
1013
0
      if (sinfo->htab->strings)
1014
0
  {
1015
0
    secinfo = merge_strings (sinfo);
1016
0
    if (!secinfo)
1017
0
      return false;
1018
0
  }
1019
0
      else
1020
0
  {
1021
0
    struct sec_merge_hash_entry *e = sinfo->htab->first;
1022
0
    bfd_size_type size = 0;  /* Octets.  */
1023
1024
    /* Things are much simpler for non-strings.
1025
       Just assign them slots in the section.  */
1026
0
    secinfo = sinfo->chain;
1027
0
    BFD_ASSERT (!secinfo->first_str);
1028
0
    secinfo->first_str = e;
1029
0
    for (e = sinfo->htab->first; e; e = e->next)
1030
0
      {
1031
0
        if (e->alignment)
1032
0
    {
1033
0
      size = (size + e->alignment - 1)
1034
0
       & ~((bfd_vma) e->alignment - 1);
1035
0
      e->u.index = size;
1036
0
      size += e->len;
1037
0
    }
1038
0
      }
1039
0
    secinfo->sec->size = size;
1040
0
  }
1041
1042
      /* If the input sections were padded according to their alignments,
1043
   then pad the output too.  */
1044
0
      if (align)
1045
0
  secinfo->sec->size = (secinfo->sec->size + align - 1) & -align;
1046
1047
      /* Finally remove all input sections which have not made it into
1048
   the hash table at all.  */
1049
0
      for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
1050
0
  if (secinfo->first_str == NULL
1051
0
      && secinfo->sec->sec_info_type == SEC_INFO_TYPE_MERGE)
1052
0
    secinfo->sec->flags |= SEC_EXCLUDE | SEC_KEEP;
1053
0
    }
1054
1055
0
  return true;
1056
0
}
1057
1058
/* Finish SEC_MERGE section merging.  */
1059
1060
bool
1061
bfd_merge_sections (bfd *obfd, struct bfd_link_info *info)
1062
0
{
1063
0
  const bfd *ibfd;
1064
0
  asection *sec;
1065
1066
0
  if (!obfd->xvec->merge_sections)
1067
0
    return true;
1068
1069
0
  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
1070
0
    if ((ibfd->flags & DYNAMIC) == 0)
1071
0
      for (sec = ibfd->sections; sec != NULL; sec = sec->next)
1072
0
  if ((sec->flags & SEC_MERGE) != 0
1073
0
      && !bfd_is_abs_section (sec->output_section)
1074
0
      && !_bfd_add_merge_section (obfd,
1075
0
          &info->hash->merge_info,
1076
0
          sec))
1077
0
        return false;
1078
1079
0
  if (info->hash->merge_info == NULL)
1080
0
    return true;
1081
1082
0
  return merge_sections (obfd, info, info->hash->merge_info);
1083
0
}
1084
1085
/* Write out the merged section.  */
1086
1087
bool
1088
_bfd_write_merged_section (bfd *output_bfd, asection *sec)
1089
0
{
1090
0
  struct sec_merge_sec_info *secinfo = sec->sec_info;
1091
0
  file_ptr pos;
1092
0
  unsigned char *contents;
1093
0
  Elf_Internal_Shdr *hdr = NULL;
1094
1095
0
  if (!secinfo)
1096
0
    return false;
1097
1098
0
  if (secinfo->first_str == NULL)
1099
0
    return true;
1100
1101
  /* FIXME: octets_per_byte.  */
1102
0
  if (bfd_get_flavour (output_bfd) == bfd_target_elf_flavour)
1103
0
    hdr = &elf_section_data (sec->output_section)->this_hdr;
1104
0
  if (hdr != NULL && hdr->sh_offset == (file_ptr) -1)
1105
0
    {
1106
      /* We must compress this section.  Write output to the
1107
   buffer.  */
1108
0
      contents = hdr->contents;
1109
0
      if (contents == NULL)
1110
0
  abort ();
1111
0
    }
1112
0
  else
1113
0
    {
1114
0
      contents = NULL;
1115
0
      pos = sec->output_section->filepos + sec->output_offset;
1116
0
      if (bfd_seek (output_bfd, pos, SEEK_SET) != 0)
1117
0
  return false;
1118
0
    }
1119
1120
0
  BFD_ASSERT (sec == secinfo->sec);
1121
0
  BFD_ASSERT (secinfo == secinfo->sinfo->chain);
1122
0
  if (! sec_merge_emit (output_bfd, secinfo, contents))
1123
0
    return false;
1124
1125
0
  return true;
1126
0
}
1127
1128
/* Adjust an address in the SEC_MERGE section.  Given OFFSET within
1129
   *PSEC, this returns the new offset in the adjusted SEC_MERGE
1130
   section and writes the new section back into *PSEC.  */
1131
1132
bfd_vma
1133
_bfd_merged_section_offset (bfd *output_bfd ATTRIBUTE_UNUSED, asection **psec,
1134
          bfd_vma offset)
1135
0
{
1136
0
  asection *sec = *psec;
1137
0
  struct sec_merge_sec_info *secinfo = sec->sec_info;
1138
1139
0
  if (!secinfo)
1140
0
    return offset;
1141
1142
0
  if (offset >= sec->rawsize)
1143
0
    {
1144
0
      if (offset > sec->rawsize)
1145
0
  _bfd_error_handler
1146
    /* xgettext:c-format */
1147
0
    (_("%pB: access beyond end of merged section (%" PRId64 ")"),
1148
0
     sec->owner, (int64_t) offset);
1149
0
      *psec = sec = secinfo->reprsec;
1150
0
      return sec->size;
1151
0
    }
1152
1153
0
  if (secinfo->fast_state != 2)
1154
0
    {
1155
0
      if (!secinfo->fast_state)
1156
0
  prepare_offsetmap (secinfo);
1157
0
      if (secinfo->fast_state != 2)
1158
0
  return offset;
1159
0
    }
1160
1161
0
  long lb = secinfo->ofstolowbound[offset / OFSDIV];
1162
0
  *psec = secinfo->reprsec;
1163
1164
  /* No need for bounds checking on lb, as we've added a sentinel that's
1165
     larger than any offset.  */
1166
0
  while (MAP_OFS(secinfo, lb) <= offset)
1167
0
    lb++;
1168
0
  lb--;
1169
1170
  /*printf ("YYY (%s:%s):%u -> (%s):%u\n",
1171
    sec->owner->filename, sec->name, (unsigned)offset,
1172
    (*psec)->name, (unsigned)lb);*/
1173
0
  return MAP_IDX(secinfo, lb) + offset - MAP_OFS(secinfo, lb);
1174
0
}
1175
1176
/* Tidy up when done.  */
1177
1178
void
1179
_bfd_merge_sections_free (void *xsinfo)
1180
3.65k
{
1181
3.65k
  struct sec_merge_info *sinfo;
1182
1183
3.65k
  for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next)
1184
0
    {
1185
0
      struct sec_merge_sec_info *secinfo;
1186
0
      for (secinfo = sinfo->chain; secinfo; secinfo = secinfo->next)
1187
0
  {
1188
0
    free (secinfo->ofstolowbound);
1189
0
    free (secinfo->map);
1190
0
    free (secinfo->map_ofs);
1191
0
  }
1192
0
      bfd_hash_table_free (&sinfo->htab->table);
1193
0
      free (sinfo->htab);
1194
0
    }
1195
3.65k
}