~ubuntu-branches/ubuntu/trusty/eglibc/trusty

« back to all changes in this revision

Viewing changes to elf/dl-sysdep.c

  • Committer: Package Import Robot
  • Author(s): Adam Conrad
  • Date: 2013-01-10 18:39:35 UTC
  • mfrom: (1.5.2) (4.4.24 experimental)
  • Revision ID: package-import@ubuntu.com-20130110183935-afsgfxkmg7wk5eaj
Tags: 2.17-0ubuntu1
* Merge with Debian, bringing in a new upstream and many small fixes:
  - patches/any/cvs-malloc-deadlock.diff: Dropped, merged upstream.
  - patches/ubuntu/lddebug-scopes.diff: Rebase for upstream changes.
  - patches/ubuntu/local-CVE-2012-3406.diff: Rebased against upstream.
  - patches/ubuntu/no-asm-mtune-i686.diff: Fixed in recent binutils.
* This upstream merge fixes a nasty hang in pulseaudio (LP: #1085342)
* Bump MIN_KERNEL_SUPPORTED to 2.6.32 on ARM, now that we no longer
  have to support shonky 2.6.31 kernels on imx51 babbage builders.
* Drop patches/ubuntu/local-disable-nscd-host-caching.diff, as these
  issues were apparently resolved upstream a while ago (LP: #613662)
* Fix the compiled-in bug URL to point to launchpad.net, not Debian.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Operating system support for run-time dynamic linker.  Generic Unix version.
2
 
   Copyright (C) 1995-1998,2000-2010,2012
3
 
        Free Software Foundation, Inc.
 
2
   Copyright (C) 1995-2012 Free Software Foundation, Inc.
4
3
   This file is part of the GNU C Library.
5
4
 
6
5
   The GNU C Library is free software; you can redistribute it and/or
17
16
   License along with the GNU C Library; if not, see
18
17
   <http://www.gnu.org/licenses/>.  */
19
18
 
 
19
/* We conditionalize the whole of this file rather than simply eliding it
 
20
   from the static build, because other sysdeps/ versions of this file
 
21
   might define things needed by a static build.  */
 
22
 
 
23
#ifdef SHARED
 
24
 
20
25
#include <assert.h>
21
26
#include <elf.h>
22
27
#include <errno.h>
39
44
#include <hp-timing.h>
40
45
#include <tls.h>
41
46
 
42
 
#ifdef _DL_FIRST_PLATFORM
43
 
# define _DL_FIRST_EXTRA (_DL_FIRST_PLATFORM + _DL_PLATFORMS_COUNT)
44
 
#else
45
 
# define _DL_FIRST_EXTRA _DL_HWCAP_COUNT
46
 
#endif
47
 
 
48
47
extern char **_environ attribute_hidden;
49
48
extern char _end[] attribute_hidden;
50
49
 
345
344
    }
346
345
}
347
346
 
348
 
 
349
 
/* Return an array of useful/necessary hardware capability names.  */
350
 
const struct r_strlenpair *
351
 
internal_function
352
 
_dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
353
 
                      size_t *max_capstrlen)
354
 
{
355
 
  /* Determine how many important bits are set.  */
356
 
  uint64_t masked = GLRO(dl_hwcap) & GLRO(dl_hwcap_mask);
357
 
  size_t cnt = platform != NULL;
358
 
  size_t n, m;
359
 
  size_t total;
360
 
  struct r_strlenpair *temp;
361
 
  struct r_strlenpair *result;
362
 
  struct r_strlenpair *rp;
363
 
  char *cp;
364
 
 
365
 
  /* Count the number of bits set in the masked value.  */
366
 
  for (n = 0; (~((1ULL << n) - 1) & masked) != 0; ++n)
367
 
    if ((masked & (1ULL << n)) != 0)
368
 
      ++cnt;
369
 
 
370
 
#if (defined NEED_DL_SYSINFO || defined NEED_DL_SYSINFO_DSO) && defined SHARED
371
 
  /* The system-supplied DSO can contain a note of type 2, vendor "GNU".
372
 
     This gives us a list of names to treat as fake hwcap bits.  */
373
 
 
374
 
  const char *dsocaps = NULL;
375
 
  size_t dsocapslen = 0;
376
 
  if (GLRO(dl_sysinfo_map) != NULL)
377
 
    {
378
 
      const ElfW(Phdr) *const phdr = GLRO(dl_sysinfo_map)->l_phdr;
379
 
      const ElfW(Word) phnum = GLRO(dl_sysinfo_map)->l_phnum;
380
 
      for (uint_fast16_t i = 0; i < phnum; ++i)
381
 
        if (phdr[i].p_type == PT_NOTE)
382
 
          {
383
 
            const ElfW(Addr) start = (phdr[i].p_vaddr
384
 
                                      + GLRO(dl_sysinfo_map)->l_addr);
385
 
            const struct
386
 
            {
387
 
              ElfW(Word) vendorlen;
388
 
              ElfW(Word) datalen;
389
 
              ElfW(Word) type;
390
 
            } *note = (const void *) start;
391
 
            while ((ElfW(Addr)) (note + 1) - start < phdr[i].p_memsz)
392
 
              {
393
 
#define ROUND(len) (((len) + sizeof (ElfW(Word)) - 1) & -sizeof (ElfW(Word)))
394
 
                if (note->type == NT_GNU_HWCAP
395
 
                    && note->vendorlen == sizeof "GNU"
396
 
                    && !memcmp ((note + 1), "GNU", sizeof "GNU")
397
 
                    && note->datalen > 2 * sizeof (ElfW(Word)) + 2)
398
 
                  {
399
 
                    const ElfW(Word) *p = ((const void *) (note + 1)
400
 
                                           + ROUND (sizeof "GNU"));
401
 
                    cnt += *p++;
402
 
                    ++p;        /* Skip mask word.  */
403
 
                    dsocaps = (const char *) p;
404
 
                    dsocapslen = note->datalen - sizeof *p * 2;
405
 
                    break;
406
 
                  }
407
 
                note = ((const void *) (note + 1)
408
 
                        + ROUND (note->vendorlen) + ROUND (note->datalen));
409
 
#undef ROUND
410
 
              }
411
 
            if (dsocaps != NULL)
412
 
              break;
413
 
          }
414
 
    }
415
 
#endif
416
 
 
417
 
  /* For TLS enabled builds always add 'tls'.  */
418
 
  ++cnt;
419
 
 
420
 
  if (__access ("/etc/ld.so.nohwcap", F_OK) == 0)
421
 
    {
422
 
      /* If hwcap is disabled, we only have the base directory to search.  */
423
 
      result = (struct r_strlenpair *) malloc (sizeof (*result));
424
 
      if (result == NULL)
425
 
        goto no_memory;
426
 
 
427
 
      result[0].str = (char *) result;  /* Does not really matter.  */
428
 
      result[0].len = 0;
429
 
 
430
 
      *sz = 1;
431
 
      return result;
432
 
    }
433
 
 
434
 
  /* Create temporary data structure to generate result table.  */
435
 
  temp = (struct r_strlenpair *) alloca (cnt * sizeof (*temp));
436
 
  m = 0;
437
 
#if defined NEED_DL_SYSINFO || defined NEED_DL_SYSINFO_DSO
438
 
  if (dsocaps != NULL)
439
 
    {
440
 
      const ElfW(Word) mask = ((const ElfW(Word) *) dsocaps)[-1];
441
 
      GLRO(dl_hwcap) |= (uint64_t) mask << _DL_FIRST_EXTRA;
442
 
      /* Note that we add the dsocaps to the set already chosen by the
443
 
         LD_HWCAP_MASK environment variable (or default HWCAP_IMPORTANT).
444
 
         So there is no way to request ignoring an OS-supplied dsocap
445
 
         string and bit like you can ignore an OS-supplied HWCAP bit.  */
446
 
      GLRO(dl_hwcap_mask) |= (uint64_t) mask << _DL_FIRST_EXTRA;
447
 
      size_t len;
448
 
      for (const char *p = dsocaps; p < dsocaps + dsocapslen; p += len + 1)
449
 
        {
450
 
          uint_fast8_t bit = *p++;
451
 
          len = strlen (p);
452
 
 
453
 
          /* Skip entries that are not enabled in the mask word.  */
454
 
          if (__builtin_expect (mask & ((ElfW(Word)) 1 << bit), 1))
455
 
            {
456
 
              temp[m].str = p;
457
 
              temp[m].len = len;
458
 
              ++m;
459
 
            }
460
 
          else
461
 
            --cnt;
462
 
        }
463
 
    }
464
 
#endif
465
 
  for (n = 0; masked != 0; ++n)
466
 
    if ((masked & (1ULL << n)) != 0)
467
 
      {
468
 
        temp[m].str = _dl_hwcap_string (n);
469
 
        temp[m].len = strlen (temp[m].str);
470
 
        masked ^= 1ULL << n;
471
 
        ++m;
472
 
      }
473
 
  if (platform != NULL)
474
 
    {
475
 
      temp[m].str = platform;
476
 
      temp[m].len = platform_len;
477
 
      ++m;
478
 
    }
479
 
 
480
 
  temp[m].str = "tls";
481
 
  temp[m].len = 3;
482
 
  ++m;
483
 
 
484
 
  assert (m == cnt);
485
 
 
486
 
  /* Determine the total size of all strings together.  */
487
 
  if (cnt == 1)
488
 
    total = temp[0].len + 1;
489
 
  else
490
 
    {
491
 
      total = temp[0].len + temp[cnt - 1].len + 2;
492
 
      if (cnt > 2)
493
 
        {
494
 
          total <<= 1;
495
 
          for (n = 1; n + 1 < cnt; ++n)
496
 
            total += temp[n].len + 1;
497
 
          if (cnt > 3
498
 
              && (cnt >= sizeof (size_t) * 8
499
 
                  || total + (sizeof (*result) << 3)
500
 
                     >= (1UL << (sizeof (size_t) * 8 - cnt + 3))))
501
 
            _dl_signal_error (ENOMEM, NULL, NULL,
502
 
                              N_("cannot create capability list"));
503
 
 
504
 
          total <<= cnt - 3;
505
 
        }
506
 
    }
507
 
 
508
 
  /* The result structure: we use a very compressed way to store the
509
 
     various combinations of capability names.  */
510
 
  *sz = 1 << cnt;
511
 
  result = (struct r_strlenpair *) malloc (*sz * sizeof (*result) + total);
512
 
  if (result == NULL)
513
 
    {
514
 
    no_memory:
515
 
      _dl_signal_error (ENOMEM, NULL, NULL,
516
 
                        N_("cannot create capability list"));
517
 
    }
518
 
 
519
 
  if (cnt == 1)
520
 
    {
521
 
      result[0].str = (char *) (result + *sz);
522
 
      result[0].len = temp[0].len + 1;
523
 
      result[1].str = (char *) (result + *sz);
524
 
      result[1].len = 0;
525
 
      cp = __mempcpy ((char *) (result + *sz), temp[0].str, temp[0].len);
526
 
      *cp = '/';
527
 
      *sz = 2;
528
 
      *max_capstrlen = result[0].len;
529
 
 
530
 
      return result;
531
 
    }
532
 
 
533
 
  /* Fill in the information.  This follows the following scheme
534
 
     (indeces from TEMP for four strings):
535
 
        entry #0: 0, 1, 2, 3    binary: 1111
536
 
              #1: 0, 1, 3               1101
537
 
              #2: 0, 2, 3               1011
538
 
              #3: 0, 3                  1001
539
 
     This allows the representation of all possible combinations of
540
 
     capability names in the string.  First generate the strings.  */
541
 
  result[1].str = result[0].str = cp = (char *) (result + *sz);
542
 
#define add(idx) \
543
 
      cp = __mempcpy (__mempcpy (cp, temp[idx].str, temp[idx].len), "/", 1);
544
 
  if (cnt == 2)
545
 
    {
546
 
      add (1);
547
 
      add (0);
548
 
    }
549
 
  else
550
 
    {
551
 
      n = 1 << (cnt - 1);
552
 
      do
553
 
        {
554
 
          n -= 2;
555
 
 
556
 
          /* We always add the last string.  */
557
 
          add (cnt - 1);
558
 
 
559
 
          /* Add the strings which have the bit set in N.  */
560
 
          for (m = cnt - 2; m > 0; --m)
561
 
            if ((n & (1 << m)) != 0)
562
 
              add (m);
563
 
 
564
 
          /* Always add the first string.  */
565
 
          add (0);
566
 
        }
567
 
      while (n != 0);
568
 
    }
569
 
#undef add
570
 
 
571
 
  /* Now we are ready to install the string pointers and length.  */
572
 
  for (n = 0; n < (1UL << cnt); ++n)
573
 
    result[n].len = 0;
574
 
  n = cnt;
575
 
  do
576
 
    {
577
 
      size_t mask = 1 << --n;
578
 
 
579
 
      rp = result;
580
 
      for (m = 1 << cnt; m > 0; ++rp)
581
 
        if ((--m & mask) != 0)
582
 
          rp->len += temp[n].len + 1;
583
 
    }
584
 
  while (n != 0);
585
 
 
586
 
  /* The first half of the strings all include the first string.  */
587
 
  n = (1 << cnt) - 2;
588
 
  rp = &result[2];
589
 
  while (n != (1UL << (cnt - 1)))
590
 
    {
591
 
      if ((--n & 1) != 0)
592
 
        rp[0].str = rp[-2].str + rp[-2].len;
593
 
      else
594
 
        rp[0].str = rp[-1].str;
595
 
      ++rp;
596
 
    }
597
 
 
598
 
  /* The second half starts right after the first part of the string of
599
 
     the corresponding entry in the first half.  */
600
 
  do
601
 
    {
602
 
      rp[0].str = rp[-(1 << (cnt - 1))].str + temp[cnt - 1].len + 1;
603
 
      ++rp;
604
 
    }
605
 
  while (--n != 0);
606
 
 
607
 
  /* The maximum string length.  */
608
 
  *max_capstrlen = result[0].len;
609
 
 
610
 
  return result;
611
 
}
 
347
#endif