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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [config/] [pa/] [fptr.c] - Blame information for rev 816

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 julius
/* Subroutine for function pointer canonicalization on PA-RISC with ELF32.
2
   Copyright 2002, 2003, 2004, 2007 Free Software Foundation, Inc.
3
   Contributed by John David Anglin (dave.anglin@nrc.ca).
4
 
5
This file is part of GCC.
6
 
7
GCC is free software; you can redistribute it and/or modify it under
8
the terms of the GNU General Public License as published by the Free
9
Software Foundation; either version 3, or (at your option) any later
10
version.
11
 
12
In addition to the permissions in the GNU General Public License, the
13
Free Software Foundation gives you unlimited permission to link the
14
compiled version of this file into combinations with other programs,
15
and to distribute those combinations without any restriction coming
16
from the use of this file.  (The General Public License restrictions
17
do apply in other respects; for example, they cover modification of
18
the file, and distribution when not linked into a combine
19
executable.)
20
 
21
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
22
WARRANTY; without even the implied warranty of MERCHANTABILITY or
23
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
24
for more details.
25
 
26
You should have received a copy of the GNU General Public License
27
along with GCC; see the file COPYING3.  If not see
28
<http://www.gnu.org/licenses/>.  */
29
 
30
/* WARNING: The code is this function depends on internal and undocumented
31
   details of the GNU linker and dynamic loader as implemented for parisc
32
   linux.  */
33
 
34
/* This MUST match the defines sysdeps/hppa/dl-machine.h and
35
   bfd/elf32-hppa.c.  */
36
#define GOT_FROM_PLT_STUB (4*4)
37
 
38
/* List of byte offsets in _dl_runtime_resolve to search for "bl" branches.
39
   The first "bl" branch instruction found MUST be a call to fixup.  See
40
   the define for TRAMPOLINE_TEMPLATE in sysdeps/hppa/dl-machine.h.  If
41
   the trampoline template is changed, the list must be appropriately
42
   updated.  The offset of -4 allows for a magic branch at the start of
43
   the template should it be necessary to change the current branch
44
   position.  */
45
#define NOFFSETS 2
46
static int fixup_branch_offset[NOFFSETS] = { 32, -4 };
47
 
48
#define GET_FIELD(X, FROM, TO) \
49
  ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
50
#define SIGN_EXTEND(VAL,BITS) \
51
  ((int) ((VAL) >> ((BITS) - 1) ? (-1 << (BITS)) | (VAL) : (VAL)))
52
 
53
struct link_map;
54
typedef int (*fptr_t) (void);
55
typedef int (*fixup_t) (struct link_map *, unsigned int);
56
extern unsigned int _GLOBAL_OFFSET_TABLE_;
57
 
58
/* __canonicalize_funcptr_for_compare must be hidden so that it is not
59
   placed in the dynamic symbol table.  Like millicode functions, it
60
   must be linked into all binaries in order access the got table of
61
   that binary.  However, we don't use the millicode calling convention
62
   and the routine must be a normal function so that it can be compiled
63
   as pic code.  */
64
unsigned int __canonicalize_funcptr_for_compare (fptr_t)
65
      __attribute__ ((visibility ("hidden")));
66
 
67
unsigned int
68
__canonicalize_funcptr_for_compare (fptr_t fptr)
69
{
70
  static unsigned int fixup_plabel[2];
71
  static fixup_t fixup;
72
  unsigned int *plabel, *got;
73
 
74
  /* -1 and page 0 are special.  -1 is used in crtend to mark the end of
75
     a list of function pointers.  Also return immediately if the plabel
76
     bit is not set in the function pointer.  In this case, the function
77
     pointer points directly to the function.  */
78
  if ((int) fptr == -1 || (unsigned int) fptr < 4096 || !((int) fptr & 2))
79
    return (unsigned int) fptr;
80
 
81
  /* The function pointer points to a function descriptor (plabel).  If
82
     the plabel hasn't been resolved, the first word of the plabel points
83
     to the entry of the PLT stub just before the global offset table.
84
     The second word in the plabel contains the relocation offset for the
85
     function.  */
86
  plabel = (unsigned int *) ((unsigned int) fptr & ~3);
87
  got = (unsigned int *) (plabel[0] + GOT_FROM_PLT_STUB);
88
 
89
  /* Return the address of the function if the plabel has been resolved.  */
90
  if (got !=  &_GLOBAL_OFFSET_TABLE_)
91
    return plabel[0];
92
 
93
  /* Initialize our plabel for calling fixup if we haven't done so already.
94
     This code needs to be thread safe but we don't have to be too careful
95
     as the result is invariant.  */
96
  if (!fixup)
97
    {
98
      int i;
99
      unsigned int *iptr;
100
 
101
      /* Find the first "bl" branch in the offset search list.  This is a
102
         call to fixup or a magic branch to fixup at the beginning of the
103
         trampoline template.  The fixup function does the actual runtime
104
         resolution of function descriptors.  We only look for "bl" branches
105
         with a 17-bit pc-relative displacement.  */
106
      for (i = 0; i < NOFFSETS; i++)
107
        {
108
          iptr = (unsigned int *) (got[-2] + fixup_branch_offset[i]);
109
          if ((*iptr & 0xfc00e000) == 0xe8000000)
110
            break;
111
        }
112
 
113
      /* This should not happen... */
114
      if (i == NOFFSETS)
115
        return ~0;
116
 
117
      /* Extract the 17-bit displacement from the instruction.  */
118
      iptr += SIGN_EXTEND (GET_FIELD (*iptr, 19, 28) |
119
                           GET_FIELD (*iptr, 29, 29) << 10 |
120
                           GET_FIELD (*iptr, 11, 15) << 11 |
121
                           GET_FIELD (*iptr, 31, 31) << 16, 17);
122
 
123
      /* Build a plabel for an indirect call to fixup.  */
124
      fixup_plabel[0] = (unsigned int) iptr + 8;  /* address of fixup */
125
      fixup_plabel[1] = got[-1];                  /* ltp for fixup */
126
      fixup = (fixup_t) ((int) fixup_plabel | 3);
127
    }
128
 
129
  /* Call fixup to resolve the function address.  got[1] contains the
130
     link_map pointer and plabel[1] the relocation offset.  */
131
  fixup ((struct link_map *) got[1], plabel[1]);
132
 
133
  return plabel[0];
134
}

powered by: WebSVN 2.1.0

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