2006-05-15 Carlos O'Donell <carlos@systemhalted.org>
authorCarlos O'Donell <carlos@systemhalted.org>
Sun, 14 May 2006 23:54:47 +0000 (23:54 +0000)
committerCarlos O'Donell <carlos@systemhalted.org>
Sun, 14 May 2006 23:54:47 +0000 (23:54 +0000)
* sysdeps/hppa/dl-machine.h: Include tls.h
(elf_machine_fixup_plt): Returns fdesc.
(elf_machine_profile_fixup_plt): Remove.
(elf_machine_plt_value): Returns fdesc.
(elf_machine_runtime_setup): Check that dl_profile != NULL.
(ARCH_LA_PLTENT, ARCH_LA_PLTEXIT): Define.
(RTLD_START): Use iitlbp with sr0.
(elf_machine_type_class): Include TLS relocs.
(reassemble_21, reassemble_14): Define.
(elf_machine_rela): Add DIR21L, DIR14R, PLABEL21L, PLABEL14R,
TLS_DTPMOD32, TLS_TPREL32, TLS_DTPOFF32 support.
(TRAMPOLINE_TEMPLATE): Move to ...
* sysdeps/hppa/dl-trampoline.S: ... here.
* sysdeps/hppa/abort-instr.h: Use iitlbp with sr0.
* sysdeps/hppa/dl-lookupcfg.h: Inlcude dl-fptr.h.
(DL_FIXUP_VALUE_TYPE, DL_FIXUP_MAKE_VALUE, DL_FIXUP_VALUE_CODE_ADDR,
DL_FIXUP_VALUE_ADD, DL_FIXUP_ADDR_VALUE): Define.
* sysdeps/hppa/sysdep.h: Use "!" as a separator. Cleanup comments.
* sysdeps/hppa/bits/link.h (La_hppa_regs, La_hppa_retval): Define.
Define prototypes for la_hppa_gnu_pltenter and la_hppa_gnu_pltexit.

ChangeLog.hppa
sysdeps/hppa/abort-instr.h
sysdeps/hppa/bits/link.h
sysdeps/hppa/dl-lookupcfg.h
sysdeps/hppa/dl-machine.h
sysdeps/hppa/dl-trampoline.S [new file with mode: 0644]
sysdeps/hppa/sysdep.h

index b927ecf..d3be675 100644 (file)
@@ -1,3 +1,26 @@
+2006-05-15  Carlos O'Donell  <carlos@systemhalted.org>
+
+       * sysdeps/hppa/dl-machine.h: Include tls.h
+       (elf_machine_fixup_plt): Returns fdesc.
+       (elf_machine_profile_fixup_plt): Remove.
+       (elf_machine_plt_value): Returns fdesc.
+       (elf_machine_runtime_setup): Check that dl_profile != NULL.
+       (ARCH_LA_PLTENT, ARCH_LA_PLTEXIT): Define.
+       (RTLD_START): Use iitlbp with sr0.
+       (elf_machine_type_class): Include TLS relocs.
+       (reassemble_21, reassemble_14): Define.
+       (elf_machine_rela): Add DIR21L, DIR14R, PLABEL21L, PLABEL14R,
+       TLS_DTPMOD32, TLS_TPREL32, TLS_DTPOFF32 support.
+       (TRAMPOLINE_TEMPLATE): Move to ...
+       * sysdeps/hppa/dl-trampoline.S: ... here.
+       * sysdeps/hppa/abort-instr.h: Use iitlbp with sr0.
+       * sysdeps/hppa/dl-lookupcfg.h: Inlcude dl-fptr.h.
+       (DL_FIXUP_VALUE_TYPE, DL_FIXUP_MAKE_VALUE, DL_FIXUP_VALUE_CODE_ADDR,
+       DL_FIXUP_VALUE_ADD, DL_FIXUP_ADDR_VALUE): Define.
+       * sysdeps/hppa/sysdep.h: Use "!" as a separator. Cleanup comments.
+       * sysdeps/hppa/bits/link.h (La_hppa_regs, La_hppa_retval): Define.
+       Define prototypes for la_hppa_gnu_pltenter and la_hppa_gnu_pltexit.
+
 2006-04-27  Carlos O'Donell  <carlos@systemhalted.org>
 
        * sysdeps/unix/sysv/linux/hppa/bits/fcntl.h: Include uio.h, and
index f1afea4..c13b0e5 100644 (file)
@@ -3,4 +3,4 @@
    We go with iitlbp because it has a history of being used to crash
    programs.  */
 
-#define ABORT_INSTRUCTION asm ("iitlbp %r0,(%r0)")
+#define ABORT_INSTRUCTION asm ("iitlbp %r0,(%sr0, %r0)")
index e69de29..2c1c81d 100644 (file)
@@ -0,0 +1,57 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef        _LINK_H
+# error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+/* Registers for entry into PLT on hppa.  */
+typedef struct La_hppa_regs
+{
+  uint32_t lr_reg[4];
+  double lr_fpreg[4];
+  uint32_t lr_sp;
+  uint32_t lr_ra;
+} La_hppa_regs;
+
+/* Return values for calls from PLT on hppa.  */
+typedef struct La_hppa_retval
+{
+  uint32_t lrv_r28;
+  uint32_t lrv_r29;
+  double lr_fr4;
+} La_hppa_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf32_Addr la_hppa_gnu_pltenter (Elf32_Sym *__sym, unsigned int __ndx,
+                                      uintptr_t *__refcook,
+                                      uintptr_t *__defcook,
+                                      La_hppa_regs *__regs,
+                                      unsigned int *__flags,
+                                      const char *__symname,
+                                      long int *__framesizep);
+extern unsigned int la_hppa_gnu_pltexit (Elf32_Sym *__sym, unsigned int __ndx,
+                                       uintptr_t *__refcook,
+                                       uintptr_t *__defcook,
+                                       const La_hppa_regs *__inregs,
+                                       La_hppa_retval *__outregs,
+                                       const char *symname);
+
+__END_DECLS
index 84436e7..89a2d22 100644 (file)
@@ -20,6 +20,8 @@
 #define ELF_FUNCTION_PTR_IS_SPECIAL
 #define DL_UNMAP_IS_SPECIAL
 
+#include <dl-fptr.h>
+
 /* Forward declaration.  */
 struct link_map;
 
@@ -63,3 +65,16 @@ void _dl_unmap (struct link_map *map);
   ((Elf32_Addr)(addr) & 2 ? (addr) : DL_AUTO_FUNCTION_ADDRESS (map, addr))
 #define DL_DT_FINI_ADDRESS(map, addr) \
   ((Elf32_Addr)(addr) & 2 ? (addr) : DL_AUTO_FUNCTION_ADDRESS (map, addr))
+
+/* The type of the return value of fixup/profile_fixup */
+#define DL_FIXUP_VALUE_TYPE struct fdesc
+
+/* Construct a fixup value from the address and linkmap */
+#define DL_FIXUP_MAKE_VALUE(map, addr) \
+   ((struct fdesc) { (addr), (map)->l_info[DT_PLTGOT]->d_un.d_ptr })
+
+/* Extract the code address from a fixup value */
+#define DL_FIXUP_VALUE_CODE_ADDR(value) ((value).ip)
+#define DL_FIXUP_VALUE_ADDR(value) ((uintptr_t) &(value))
+#define DL_FIXUP_ADDR_VALUE(addr) (*(struct fdesc *) (addr))
+
index d29501d..dd5a281 100644 (file)
@@ -31,6 +31,7 @@
 #include <errno.h>
 #include <dl-fptr.h>
 #include <abort-instr.h>
+#include <tls.h>
 
 # define VALID_ELF_OSABI(osabi)                ((osabi == ELFOSABI_SYSV) || (osabi == ELFOSABI_LINUX))
 # define VALID_ELF_ABIVERSION(ver)     (ver == 0)
@@ -116,43 +117,28 @@ elf_machine_load_address (void)
   return dynamic - elf_machine_dynamic ();
 }
 
-/* Fixup a PLT entry to bounce directly to the function at VALUE.  
-   Optimized non-profile version. */
-static inline Elf32_Addr
+/* Fixup a PLT entry to bounce directly to the function at VALUE. */ 
+static inline struct fdesc __attribute__ ((always_inline)) 
 elf_machine_fixup_plt (struct link_map *map, lookup_t t,
                       const Elf32_Rela *reloc,
-                      Elf32_Addr *reloc_addr, Elf32_Addr value)
+                      Elf32_Addr *reloc_addr, struct fdesc value)
 {
   /* map is the link_map for the caller, t is the link_map for the object
      being called */
-  reloc_addr[1] = D_PTR (t, l_info[DT_PLTGOT]);
-  reloc_addr[0] = value;
-  /* Return the PLT slot rather than the function value so that the
-     trampoline can load the new LTP. */
-  return (Elf32_Addr) reloc_addr;
-}
-
-/* Fixup a PLT entry to bounce directly to the function at VALUE.  */
-#define ELF_MACHINE_PROFILE_FIXUP_PLT elf_machine_profile_fixup_plt
-static inline Elf32_Addr
-elf_machine_profile_fixup_plt (struct link_map *map, lookup_t t,
-                      const Elf32_Rela *reloc,
-                      Elf32_Addr *reloc_addr, Elf32_Addr value)
-{
-  if(__builtin_expect (t == NULL, 1)) 
-    return (Elf32_Addr) reloc_addr;
-  /* Return the PLT slot rather than the function value so that the
-     trampoline can load the new LTP. */
-  return (Elf32_Addr) elf_machine_fixup_plt(map, t, reloc, reloc_addr, value);
+  reloc_addr[1] = value.gp;
+  /* Need to ensure that the gp is visible before the code
+     entry point is updated */
+  ((volatile Elf32_Addr *) reloc_addr)[0] = value.ip;
+  return value;
 }
 
 /* Return the final value of a plt relocation.  */
-static inline Elf32_Addr
+static inline struct fdesc 
 elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
-                      Elf32_Addr value)
+                      struct fdesc value)
 {
-  /* We are rela only */
-  return value + reloc->r_addend;
+  /* We are rela only, return a function descriptor as a plt entry. */
+  return (struct fdesc) { value.ip + reloc->r_addend, value.gp };
 }
 
 /* Set up the loaded object described by L so its unrelocated PLT
@@ -181,7 +167,7 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
   
   extern void _dl_runtime_resolve (void);
   extern void _dl_runtime_profile (void);
-  
   /* Linking lazily */
   if (lazy)
     {
@@ -215,9 +201,10 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
            {
               /* Found the GOT! */             
               register Elf32_Addr ltp __asm__ ("%r19");
-              /* Identify this shared object. */
+              
+              /* Identify this shared object. Second entry in the got. */
               got[1] = (Elf32_Addr) l;
-
+              
               /* This function will be called to perform the relocation. */
               if (__builtin_expect (!profile, 1))
                 {
@@ -236,7 +223,8 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
                 }
               else
                {
-                 if (_dl_name_match_p (GLRO(dl_profile), l))
+                 if (GLRO(dl_profile) != NULL
+                     && _dl_name_match_p (GLRO(dl_profile), l))
                    {
                      /* This is the object we are looking for.  Say that
                         we really want profiling and the timers are
@@ -316,6 +304,11 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
   return lazy;
 }
 
+
+/* Names of the architecture-specific auditing callback functions.  */
+#define ARCH_LA_PLTENTER hppa_gnu_pltenter
+#define ARCH_LA_PLTEXIT hppa_gnu_pltexit
+
 /* Initial entry point code for the dynamic linker.
    The C function `_dl_start' is the real entry point;
    its return value is the user program's entry point.  */
@@ -367,7 +360,7 @@ asm (                                                                       \
 "      ldw,ma  8(%r26),%r19\n"                                         \
                                                                        \
        /* Uh oh!  We didn't find one.  Abort. */                       \
-"      iitlbp  %r0,(%r0)\n"                                            \
+"      iitlbp  %r0,(%sr0,%r0)\n"                                       \
                                                                        \
 "2:    ldw     -4(%r26),%r19\n"        /* Found it, load value. */     \
 "      add     %r19,%r20,%r19\n"       /* And add the load offset. */  \
@@ -471,85 +464,28 @@ asm (                                                                     \
 "      ldw     4(%r3),%r19\n"  /* load the object's gp */              \
 "      bv      %r0(%r2)\n"                                             \
 "      depi    2,31,2,%r23\n"  /* delay slot */                        \
-       );
-
+);
 
-/* This code gets called via the .plt stub, and is used in
-   dl-runtime.c to call the `fixup' function and then redirect to the
-   address it returns.
-   
-   WARNING: This template is also used by gcc's __cffc, and expects
-   that the "bl" for fixup() exist at a particular offset.
-   Do not change this template without changing gcc, while the prefix
-   "bl" should fix everything so gcc finds the right spot, it will
-   slow down __cffc when it attempts to call fixup to resolve function
-   descriptor references. Please refer to gcc/gcc/config/pa/fptr.c
-   
-   Enter with r19 = reloc offset, r20 = got-8, r21 = fixup ltp.  */
-#define TRAMPOLINE_TEMPLATE(tramp_name, fixup_name)                    \
-  extern void tramp_name (void);                                       \
-  asm (                                                                        \
- "     .text\n"                                                        \
-       /* FAKE bl to provide gcc's __cffc with fixup's address */      \
- "     bl      " #fixup_name ",%r2\n" /* Runtime address of fixup */   \
- "     .globl " #tramp_name "\n"                                       \
- "     .type " #tramp_name ",@function\n"                              \
-  #tramp_name ":\n"                                                    \
- "     .proc\n"                                                        \
- "     .callinfo frame=64,calls,save_rp\n"                             \
- "     .entry\n"                                                       \
-       /* Save return pointer */                                       \
- "     stw     %r2,-20(%sp)\n"                                         \
-       /* Save argument registers in the call stack frame. */          \
- "     stw     %r26,-36(%sp)\n"                                        \
- "     stw     %r25,-40(%sp)\n"                                        \
- "     stw     %r24,-44(%sp)\n"                                        \
- "     stw     %r23,-48(%sp)\n"                                        \
-       /* Build a call frame, and save structure pointer. */           \
- "     stwm    %r28,64(%sp)\n"                                         \
-                                                                       \
-       /* Set up args to fixup func.  */                               \
- "     ldw     8+4(%r20),%r26\n" /* (1) got[1] == struct link_map */   \
- "     copy    %r19,%r25\n"      /* (2) reloc offset  */               \
- "     copy    %r2,%r24\n"       /* (3) profile_fixup needs rp */      \
-                                                                       \
-       /* Call the real address resolver. */                           \
- "     bl      " #fixup_name ",%r2\n"                                  \
- "     copy    %r21,%r19\n"      /* set fixup func ltp (DELAY SLOT)*/  \
-                                                                       \
- "     ldw     0(%r28),%r22\n"   /* load up the returned func ptr */   \
- "     ldw     4(%r28),%r19\n"                                         \
- "     ldwm    -64(%sp),%r28\n"                                        \
-       /* Arguments. */                                                \
- "     ldw     -36(%sp),%r26\n"                                        \
- "     ldw     -40(%sp),%r25\n"                                        \
- "     ldw     -44(%sp),%r24\n"                                        \
- "     ldw     -48(%sp),%r23\n"                                        \
-       /* Call the real function. */                                   \
- "     bv      %r0(%r22)\n"                                            \
-       /* Return pointer. */                                           \
- "     ldw     -20(%sp),%r2\n"                                         \
- "     .exit\n"                                                        \
- "     .procend\n");
-  
-#ifndef PROF
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE                 \
-  TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup);    \
-  TRAMPOLINE_TEMPLATE (_dl_runtime_profile, profile_fixup);
-#else
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE                 \
-  TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup);    \
-  strong_alias (_dl_runtime_resolve, _dl_runtime_profile);
-#endif
-
-/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
-   PLT entries should not be allowed to define the value.
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or 
+   a TLS variable, so references should not be allowed to define the value.
    ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
    of the main executable's symbols, as for a COPY reloc.  */
-#define elf_machine_type_class(type) \
-  ((((type) == R_PARISC_IPLT || (type) == R_PARISC_EPLT)       \
-    * ELF_RTYPE_CLASS_PLT)                                     \
+#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
+# define elf_machine_type_class(type)                          \
+  ((((type) == R_PARISC_IPLT                                   \
+  || (type) == R_PARISC_EPLT                                   \
+  || (type) == R_PARISC_TLS_DTPMOD32                           \
+  || (type) == R_PARISC_TLS_DTPOFF32                           \
+  || (type) == R_PARISC_TLS_TPREL32)                           \
+  * ELF_RTYPE_CLASS_PLT)                                       \
+  | (((type) == R_PARISC_COPY) * ELF_RTYPE_CLASS_COPY))
+#else
+#define elf_machine_type_class(type)                           \
+ ((((type) == R_PARISC_IPLT                                    \
+   || (type) == R_PARISC_EPLT)                                 \
+   * ELF_RTYPE_CLASS_PLT)                                      \
    | (((type) == R_PARISC_COPY) * ELF_RTYPE_CLASS_COPY))
+#endif
 
 /* Used by the runtime in fixup to figure out if reloc is *really* PLT */
 #define ELF_MACHINE_JMP_SLOT R_PARISC_IPLT
@@ -579,9 +515,22 @@ dl_platform_init (void)
 /* These are only actually used where RESOLVE_MAP is defined, anyway. */
 #ifdef RESOLVE_MAP
 
+#define reassemble_21(as21) \
+  (  (((as21) & 0x100000) >> 20) \
+   | (((as21) & 0x0ffe00) >> 8) \
+   | (((as21) & 0x000180) << 7) \
+   | (((as21) & 0x00007c) << 14) \
+   | (((as21) & 0x000003) << 12))
+
+#define reassemble_14(as14) \
+  (  (((as14) & 0x1fff) << 1) \
+   | (((as14) & 0x2000) >> 13))
+
 auto void __attribute__((always_inline))
-elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
-                 const Elf32_Sym *sym, const struct r_found_version *version,
+elf_machine_rela (struct link_map *map, 
+                 const Elf32_Rela *reloc,
+                 const Elf32_Sym *sym, 
+                 const struct r_found_version *version,
                  void *const reloc_addr_arg)
 {
   Elf32_Addr *const reloc_addr = reloc_addr_arg;
@@ -590,7 +539,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
   struct link_map *sym_map;
   Elf32_Addr value;
 
-# if !defined RTLD_BOOTSTRAP && !defined SHARED
+# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC && !defined SHARED
   /* This is defined in rtld.c, but nowhere in the static libc.a; make the
      reference weak so static programs can still link.  This declaration
      cannot be done when compiling rtld.c (i.e.  #ifdef RTLD_BOOTSTRAP)
@@ -612,6 +561,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
 # else
   sym_map = RESOLVE_MAP (&sym, version, r_type);
 # endif
+  
   if (sym_map)
     {
       value = sym ? sym_map->l_addr + sym->st_value : 0;
@@ -635,6 +585,27 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
        }
       break;
 
+    case R_PARISC_DIR21L:
+      {
+       unsigned int insn = *(unsigned int *)reloc_addr;
+        value = sym_map->l_addr + sym->st_value 
+               + ((reloc->r_addend + 0x1000) & -0x2000);
+       value = value >> 11;
+       insn = (insn &~ 0x1fffff) | reassemble_21 (value);
+       *(unsigned int *)reloc_addr = insn;
+      }
+      return;
+
+    case R_PARISC_DIR14R:
+      {
+       unsigned int insn = *(unsigned int *)reloc_addr;
+       value = ((sym_map->l_addr + sym->st_value) & 0x7ff) 
+               + (((reloc->r_addend & 0x1fff) ^ 0x1000) - 0x1000);
+       insn = (insn &~ 0x3fff) | reassemble_14 (value);
+       *(unsigned int *)reloc_addr = insn;
+      }
+      return;
+
     case R_PARISC_PLABEL32:
       /* Easy rule: If there is a symbol and it is global, then we
          need to make a dynamic function descriptor.  Otherwise we
@@ -653,15 +624,42 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
       value = (Elf32_Addr)((unsigned int)_dl_make_fptr (sym_map, sym, value) | 2);
       break;
 
+    case R_PARISC_PLABEL21L:
+    case R_PARISC_PLABEL14R:
+      {
+       unsigned int insn = *(unsigned int *)reloc_addr;
+
+        if (__builtin_expect (sym == NULL, 0))
+          break;
+
+        value = (Elf32_Addr)((unsigned int)_dl_make_fptr (sym_map, sym, value) | 2);
+
+        if (r_type == R_PARISC_PLABEL21L)
+         {
+           value >>= 11;
+           insn = (insn &~ 0x1fffff) | reassemble_21 (value);
+         }
+        else
+         {
+           value &= 0x7ff;
+           insn = (insn &~ 0x3fff) | reassemble_14 (value);
+         }
+
+       *(unsigned int *)reloc_addr = insn;
+      }
+      return;
+
     case R_PARISC_IPLT:
       if (__builtin_expect (sym_map != NULL, 1))
         {
-         elf_machine_fixup_plt (NULL, sym_map, reloc, reloc_addr, value);
+         elf_machine_fixup_plt (NULL, sym_map, reloc, reloc_addr, 
+                                DL_FIXUP_MAKE_VALUE(sym_map, value));
         } 
       else 
         {
          /* If we get here, it's a (weak) undefined sym.  */
-         elf_machine_fixup_plt (NULL, map, reloc, reloc_addr, value);
+         elf_machine_fixup_plt (NULL, map, reloc, reloc_addr, 
+                                DL_FIXUP_MAKE_VALUE(map, value));
         }
       return;
 
@@ -685,6 +683,28 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
       memcpy (reloc_addr_arg, (void *) value,
              MIN (sym->st_size, refsym->st_size));
       return;
+
+#if defined USE_TLS && (!defined RTLD_BOOTSTRAP)
+    case R_PARISC_TLS_DTPMOD32:
+      value = sym_map->l_tls_modid;
+      break;
+
+    case R_PARISC_TLS_DTPOFF32:
+      /* During relocation all TLS symbols are defined and used.
+         Therefore the offset is already correct.  */
+      if (sym != NULL)
+        *reloc_addr = sym->st_value;
+      return;
+
+    case R_PARISC_TLS_TPREL32:
+      /* The offset is negative, forward from the thread pointer */
+      if (sym != NULL)
+        {
+          CHECK_STATIC_TLS (map, sym_map);
+         value = sym_map->l_tls_offset + sym->st_value + reloc->r_addend;
+       }
+      break;
+#endif /* use TLS */
       
     case R_PARISC_NONE:        /* Alright, Wilbur. */
       return;
diff --git a/sysdeps/hppa/dl-trampoline.S b/sysdeps/hppa/dl-trampoline.S
new file mode 100644 (file)
index 0000000..c476138
--- /dev/null
@@ -0,0 +1,197 @@
+/* PLT trampolines. hppa version.
+   Copyright (C) 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep.h>
+
+/* This code gets called via the .plt stub, and is used in
+   dl-runtime.c to call the `_dl_fixup' function and then redirect 
+   to the    address it returns. `_dl_fixup' takes two
+   arguments, however `_dl_profile_fixup' takes a number of 
+   parameters for use with library auditing (LA).
+   
+   WARNING: This template is also used by gcc's __cffc, and expects
+   that the "bl" for _dl_runtime_resolve exist at a particular offset.
+   Do not change this template without changing gcc, while the prefix
+   "bl" should fix everything so gcc finds the right spot, it will
+   slow down __cffc when it attempts to call fixup to resolve function
+   descriptor references. Please refer to gcc/gcc/config/pa/fptr.c
+   
+   Enter with r19 = reloc offset, r20 = got-8, r21 = fixup ltp.  */
+
+       /* FAKE bl to provide gcc's __cffc with fixup loc. */
+       .text
+       bl      _dl_fixup, %r2
+        .text
+        .align 4
+        .global _dl_runtime_resolve
+        .type _dl_runtime_resolve,@function
+_dl_runtime_resolve:
+        .PROC
+        .CALLINFO FRAME=128,CALLS,SAVE_RP,ENTRY_GR=3
+        .ENTRY
+        /* SAVE_RP says we do */
+        stw %rp, -20(%sp)
+
+       /* Save static link register */
+       stw     %r29,-16(%sp)
+       /* Save argument registers in the call stack frame. */
+       stw     %r26,-36(%sp)
+       stw     %r25,-40(%sp)
+       stw     %r24,-44(%sp)
+       stw     %r23,-48(%sp)
+
+       /* Build a call frame, and save structure pointer. */
+       copy    %sp, %r26       /* Copy previous sp */
+       /* Save function result address (on entry) */
+       stwm    %r28,128(%sp)
+
+       /* Save floating point argument registers */
+       ldo     -56(%sp),%r26   
+       fstd,ma %fr4,-8(%r26)
+       fstd,ma %fr5,-8(%r26)
+       fstd,ma %fr6,-8(%r26)
+       fstd    %fr7,0(%r26)
+
+       /* Fillin some frame info to follow ABI */
+       stw     %r21,-32(%sp)   /* PIC register value */
+       stw     %r26,-4(%sp)    /* Previous sp */
+
+       /* Set up args to fixup func, needs only two arguments  */
+       ldw     8+4(%r20),%r26          /* (1) got[1] == struct link_map */
+       copy    %r19,%r25               /* (2) reloc offset  */
+
+       /* Call the real address resolver. */
+       bl      _dl_fixup,%rp
+       copy    %r21,%r19               /* set fixup func ltp */
+
+       /* Load up the returned func descriptor */
+       copy    %ret0, %r22
+       copy    %ret1, %r19
+
+       /* Reload arguments fp args */
+       ldo     -80(%sp),%r26
+       fldd,ma 8(%r26),%fr7
+       fldd,ma 8(%r26),%fr6
+       fldd,ma 8(%r26),%fr5
+       fldd    0(%r26),%fr4
+
+       /* Adjust sp, and restore function result address*/
+       ldwm    -128(%sp),%r28
+
+       /* Reload static link register */
+       ldw     -16(%sp),%r29
+       /* Reload general args */
+       ldw     -36(%sp),%r26
+       ldw     -40(%sp),%r25
+       ldw     -44(%sp),%r24
+       ldw     -48(%sp),%r23
+
+       /* Jump to new function, but return to previous function */
+       bv      %r0(%r22)
+       ldw     -20(%sp),%rp
+        .EXIT
+        .PROCEND
+       .size   _dl_runtime_resolve, . - _dl_runtime_resolve
+
+
+       /* FIXME:
+               Need to largely rewrite the bottom half of
+               this code in order to save and restore the
+               LA struct from the stack along with
+               interpreted parameters.
+       */
+        .text
+        .align 4
+        .global _dl_runtime_profile
+        .type _dl_runtime_profile,@function
+_dl_runtime_profile:
+        .PROC
+        .CALLINFO FRAME=128,CALLS,SAVE_RP,ENTRY_GR=3
+        .ENTRY
+
+        /* SAVE_RP says we do */
+        stw %rp, -20(%sp)
+
+       /* Save static link register */
+       stw     %r29,-16(%sp)
+       /* Save argument registers in the call stack frame. */
+       stw     %r26,-36(%sp)
+       stw     %r25,-40(%sp)
+       stw     %r24,-44(%sp)
+       stw     %r23,-48(%sp)
+
+       /* Build a call frame, and save structure pointer. */
+       copy    %sp, %r26       /* Copy previous sp */
+       /* Save function result address (on entry) */
+       stwm    %r28,128(%sp)
+
+       /* Save floating point argument registers */
+       ldo     -56(%sp),%r26   
+       fstd,ma %fr4,-8(%r26)
+       fstd,ma %fr5,-8(%r26)
+       fstd,ma %fr6,-8(%r26)
+       fstd    %fr7,0(%r26)
+
+       /* Fillin some frame info to follow ABI */
+       stw     %r21,-32(%sp)   /* PIC register value */
+       stw     %r26,-4(%sp)    /* Previous sp */
+
+       /* Set up args to fixup func, needs five arguments  */
+       ldw     8+4(%r20),%r26          /* (1) got[1] == struct link_map */
+       copy    %r19,%r25               /* (2) reloc offset  */
+       copy    %rp,%r24                /* (3) profile_fixup needs rp */
+       copy    %r0,%r23                /* (4) regs */
+       ldo     -56(%sp), %r1
+       stw     %r1, -52(%sp)           /* (5) long int *framesizep */
+
+       /* Call the real address resolver. */
+       bl      _dl_profile_fixup,%rp
+       copy    %r21,%r19               /* set fixup func ltp */
+
+       /* Load up the returned func descriptor */
+       copy    %ret0, %r22
+       copy    %ret1, %r19
+
+       /* Reload arguments fp args */
+       ldo     -80(%sp),%r26
+       fldd,ma 8(%r26),%fr7
+       fldd,ma 8(%r26),%fr6
+       fldd,ma 8(%r26),%fr5
+       fldd    0(%r26),%fr4
+
+       /* Adjust sp, and restore function result address*/
+       ldwm    -128(%sp),%r28
+
+       /* Reload static link register */
+       ldw     -16(%sp),%r29
+       /* Reload general args */
+       ldw     -36(%sp),%r26
+       ldw     -40(%sp),%r25
+       ldw     -44(%sp),%r24
+       ldw     -48(%sp),%r23
+
+       /* Jump to new function, but return to previous function */
+       bv      %r0(%r22)
+       ldw     -20(%sp),%rp
+        .EXIT
+        .PROCEND
+       .size   _dl_runtime_profile, . - _dl_runtime_profile
+
+
+
index be36567..5d02f37 100644 (file)
@@ -22,9 +22,8 @@
 #include <sys/syscall.h>
 #include "config.h"
 
-#ifndef ASM_LINE_SEP
-#define ASM_LINE_SEP ;
-#endif
+#undef ASM_LINE_SEP
+#define ASM_LINE_SEP ! 
 
 #ifdef __ASSEMBLER__
 
 #define END(name)                                                            \
   .PROCEND
 
-
-/* If compiled for profiling, call `mcount' at the start of each function.  */
+/* GCC does everything for us. */
 #ifdef PROF
-/* The mcount code relies on a normal frame pointer being on the stack
-   to locate our caller, so push one just for its benefit.  */
-#define CALL_MCOUNT \
-  XXX  ASM_LINE_SEP
+#define CALL_MCOUNT 
 #else
 #define CALL_MCOUNT            /* Do nothing.  */
 #endif