~ubuntu-branches/ubuntu/utopic/binutils-arm64-cross/utopic

« back to all changes in this revision

Viewing changes to binutils-2.23.52.20130611/gold/testsuite/ifunc-sel.h

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2013-06-20 17:38:09 UTC
  • Revision ID: package-import@ubuntu.com-20130620173809-app8lzgvymy5fg6c
Tags: 0.7
Build-depend on binutils-source (>= 2.23.52.20130620-1~).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Used by the elf ifunc tests.  */
 
2
#ifndef ELF_IFUNC_SEL_H
 
3
#define ELF_IFUNC_SEL_H 1
 
4
 
 
5
extern int global;
 
6
 
 
7
static inline __attribute__ ((always_inline)) void *
 
8
ifunc_sel (int (*f1) (void), int (*f2) (void), int (*f3) (void))
 
9
{
 
10
#ifdef __powerpc__
 
11
  /* When generating PIC, powerpc gcc loads the address of "global"
 
12
     from the GOT, but the GOT may not have been relocated.
 
13
     Similarly, "f1", "f2" and "f3" may be loaded from non-relocated
 
14
     GOT entries.
 
15
 
 
16
     There is NO WAY to make this ill conceived IFUNC misfeature
 
17
     reliably work on targets that use a GOT for function or variable
 
18
     addresses, short of implementing two passes over relocations in
 
19
     ld.so, with ifunc relocations being applied after all other
 
20
     relocations, globally.
 
21
 
 
22
     Cheat.  Don't use the GOT.  Rely on this function being inlined
 
23
     and calculate all variable and function addresses relative to pc.
 
24
     Using the 'X' constraint is risky, but that's the only way to
 
25
     make the asm here see the function names for %4, %5 and %6.
 
26
     Sadly, powerpc64 gcc doesn't accept use of %3 here with 'X' for
 
27
     some reason, so we expand it ourselves.  */
 
28
  register void *ret __asm__ ("r3");
 
29
  void *temp1, *temp2;
 
30
  __asm__ ("mflr %1\n\t"
 
31
           "bcl 20,31,1f\n"
 
32
           "1:\tmflr %2\n\t"
 
33
           "mtlr %1\n\t"
 
34
           "addis %1,%2,global-1b@ha\n\t"
 
35
           "lwz %1,global-1b@l(%1)\n\t"
 
36
           "addis %0,%2,%4-1b@ha\n\t"
 
37
           "addi %0,%0,%4-1b@l\n\t"
 
38
           "cmpwi %1,1\n\t"
 
39
           "beqlr\n\t"
 
40
           "addis %0,%2,%5-1b@ha\n\t"
 
41
           "addi %0,%0,%5-1b@l\n\t"
 
42
           "cmpwi %1,-1\n\t"
 
43
           "beqlr\n\t"
 
44
           "addis %0,%2,%6-1b@ha\n\t"
 
45
           "addi %0,%0,%6-1b@l"
 
46
           : "=&b" (ret), "=&b" (temp1), "=&b" (temp2)
 
47
           : "X" (&global), "X" (f1), "X" (f2), "X" (f3));
 
48
  return ret;
 
49
#else
 
50
  switch (global)
 
51
    {
 
52
    case 1:
 
53
      return f1;
 
54
    case -1:
 
55
      return f2;
 
56
    default:
 
57
      return f3;
 
58
    }
 
59
#endif
 
60
}
 
61
 
 
62
static inline __attribute__ ((always_inline)) void *
 
63
ifunc_one (int (*f1) (void))
 
64
{
 
65
#ifdef __powerpc__
 
66
  /* As above, PIC may use an unrelocated GOT entry for f1.
 
67
 
 
68
     Case study: ifuncmain6pie's shared library, ifuncmod6.so, wants
 
69
     the address of "foo" in function get_foo().  So there is a GOT
 
70
     entry for "foo" in ifuncmod6.so.  ld.so relocates ifuncmod6.so
 
71
     *before* ifuncmain6pie, and on finding "foo" to be STT_GNU_IFUNC,
 
72
     calls this function with f1 set to "one".  But the address of
 
73
     "one" is loaded from ifuncmain6pie's GOT, which hasn't been
 
74
     relocated yet.
 
75
 
 
76
     Cheat as for ifunc-sel.  */
 
77
  register void *ret __asm__ ("r3");
 
78
  void *temp;
 
79
  __asm__ ("mflr %1\n\t"
 
80
           "bcl 20,31,1f\n"
 
81
           "1:\tmflr %0\n\t"
 
82
           "mtlr %1\n\t"
 
83
           "addis %0,%0,%2-1b@ha\n\t"
 
84
           "addi %0,%0,%2-1b@l"
 
85
           : "=&b" (ret), "=&r" (temp)
 
86
           : "X" (f1));
 
87
  return ret;
 
88
#else
 
89
  return f1;
 
90
#endif
 
91
}
 
92
#endif