2005-05-09 Daniel Jacobowitz <dan@codesourcery.com>
authorPhil Blundell <pb@reciva.com>
Fri, 10 Jun 2005 11:33:52 +0000 (11:33 +0000)
committerPhil Blundell <pb@reciva.com>
Fri, 10 Jun 2005 11:33:52 +0000 (11:33 +0000)
    Mark Mitchell  <mark@codesourcery.com>

     * sysdeps/arm/bits/link.h: New file.
* sysdeps/arm/dl-trampoline.S: New file.
* sysdeps/arm/dl-machine.h: Check RESOLVE_MAP instead of RESOLVE.
(elf_machine_runtime_setup): Check dl_profile before calling
_dl_name_match_p.
(ELF_MACHINE_RUNTIME_TRAMPOLINE): Delete.
(elf_machine_rel, elf_machine_rela): Use RESOLVE_MAP.
(fix_bad_pc24): Use auto instead of static.

ChangeLog.arm
sysdeps/arm/bits/link.h
sysdeps/arm/dl-machine.h
sysdeps/arm/dl-trampoline.S [new file with mode: 0644]

index e36328b..360b06f 100644 (file)
@@ -1,6 +1,18 @@
 2005-05-09  Daniel Jacobowitz  <dan@codesourcery.com>
            Mark Mitchell  <mark@codesourcery.com>
 
+       * sysdeps/arm/bits/link.h: New file.
+       * sysdeps/arm/dl-trampoline.S: New file.
+       * sysdeps/arm/dl-machine.h: Check RESOLVE_MAP instead of RESOLVE.
+       (elf_machine_runtime_setup): Check dl_profile before calling
+       _dl_name_match_p.
+       (ELF_MACHINE_RUNTIME_TRAMPOLINE): Delete.
+       (elf_machine_rel, elf_machine_rela): Use RESOLVE_MAP.
+       (fix_bad_pc24): Use auto instead of static.
+
+2005-05-09  Daniel Jacobowitz  <dan@codesourcery.com>
+           Mark Mitchell  <mark@codesourcery.com>
+
        * sysdeps/unix/sysv/linux/arm/ioperm.c (BUS_ISA): Define for new
        kernel headers.
 
index e69de29..8dbd2c7 100644 (file)
@@ -0,0 +1,66 @@
+/* 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 ARM.  */
+typedef struct La_arm_regs
+{
+  uint32_t lr_reg[4];
+  uint32_t lr_sp;
+  uint32_t lr_lr;
+  /* Coprocessor registers used for argument passing.  The data
+     stored here depends on the coprocessors available in the
+     system which are used for function calls in the current ABI.
+     VFP uses eight 64-bit registers, and iWMMXt uses ten.  */
+  uint32_t lr_coproc[42];
+} La_arm_regs;
+
+/* Return values for calls from PLT on ARM.  */
+typedef struct La_arm_retval
+{
+  /* Up to four integer registers can be used for a return value in
+     some ABIs (APCS complex long double).  */
+  uint32_t lrv_reg[4];
+
+  /* Any coprocessor registers which might be used to return values
+     in the current ABI.  */
+  uint32_t lrv_coproc[12];
+} La_arm_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf32_Addr la_arm_gnu_pltenter (Elf32_Sym *__sym, unsigned int __ndx,
+                                      uintptr_t *__refcook,
+                                      uintptr_t *__defcook,
+                                      La_arm_regs *__regs,
+                                      unsigned int *__flags,
+                                      const char *__symname,
+                                      long int *__framesizep);
+extern unsigned int la_arm_gnu_pltexit (Elf32_Sym *__sym, unsigned int __ndx,
+                                       uintptr_t *__refcook,
+                                       uintptr_t *__defcook,
+                                       const La_arm_regs *__inregs,
+                                       La_arm_retval *__outregs,
+                                       const char *symname);
+
+__END_DECLS
index 0fe47b2..abff153 100644 (file)
@@ -110,7 +110,8 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
        {
          got[2] = (Elf32_Addr) &_dl_runtime_profile;
 
-         if (_dl_name_match_p (GLRO(dl_profile), l))
+         if (GLRO(dl_profile) != NULL
+             && _dl_name_match_p (GLRO(dl_profile), l))
            /* Say that we really want profiling and the timers are
               started.  */
            GL(dl_profile_map) = l;
@@ -129,119 +130,6 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 #define BX(x) "mov\tpc, " #x
 #endif
 
-#ifndef PROF
-# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\
-       .text\n\
-       .globl _dl_runtime_resolve\n\
-       .type _dl_runtime_resolve, #function\n\
-       .align 2\n\
-_dl_runtime_resolve:\n\
-       @ we get called with\n\
-       @       stack[0] contains the return address from this call\n\
-       @       ip contains &GOT[n+3] (pointer to function)\n\
-       @       lr points to &GOT[2]\n\
-\n\
-       @ stack arguments\n\
-       stmdb   sp!,{r0-r3}\n\
-\n\
-       @ get pointer to linker struct\n\
-       ldr     r0, [lr, #-4]\n\
-\n\
-       @ prepare to call fixup()\n\
-       @ change &GOT[n+3] into 8*n        NOTE: reloc are 8 bytes each\n\
-       sub     r1, ip, lr\n\
-       sub     r1, r1, #4\n\
-       add     r1, r1, r1\n\
-\n\
-       @ call fixup routine\n\
-       bl      fixup\n\
-\n\
-       @ save the return\n\
-       mov     ip, r0\n\
-\n\
-       @ get arguments and return address back\n\
-       ldmia   sp!, {r0-r3,lr}\n\
-\n\
-       @ jump to the newly found address\n\
-       " BX(ip) "\n\
-\n\
-       .size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
-\n\
-       .globl _dl_runtime_profile\n\
-       .type _dl_runtime_profile, #function\n\
-       .align 2\n\
-_dl_runtime_profile:\n\
-       @ stack arguments\n\
-       stmdb   sp!, {r0-r3}\n\
-\n\
-       @ get pointer to linker struct\n\
-       ldr     r0, [lr, #-4]\n\
-\n\
-       @ prepare to call fixup()\n\
-       @ change &GOT[n+3] into 8*n        NOTE: reloc are 8 bytes each\n\
-       sub     r1, ip, lr\n\
-       sub     r1, r1, #4\n\
-       add     r1, r1, r1\n\
-\n\
-       @ call profiling fixup routine\n\
-       bl      profile_fixup\n\
-\n\
-       @ save the return\n\
-       mov     ip, r0\n\
-\n\
-       @ get arguments and return address back\n\
-       ldmia   sp!, {r0-r3,lr}\n\
-\n\
-       @ jump to the newly found address\n\
-       " BX(ip) "\n\
-\n\
-       .size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
-       .previous\n\
-");
-#else // PROF
-# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\
-       .text\n\
-       .globl _dl_runtime_resolve\n\
-       .globl _dl_runtime_profile\n\
-       .type _dl_runtime_resolve, #function\n\
-       .type _dl_runtime_profile, #function\n\
-       .align 2\n\
-_dl_runtime_resolve:\n\
-_dl_runtime_profile:\n\
-       @ we get called with\n\
-       @       stack[0] contains the return address from this call\n\
-       @       ip contains &GOT[n+3] (pointer to function)\n\
-       @       lr points to &GOT[2]\n\
-\n\
-       @ stack arguments\n\
-       stmdb   sp!, {r0-r3}\n\
-\n\
-       @ get pointer to linker struct\n\
-       ldr     r0, [lr, #-4]\n\
-\n\
-       @ prepare to call fixup()\n\
-       @ change &GOT[n+3] into 8*n        NOTE: reloc are 8 bytes each\n\
-       sub     r1, ip, lr\n\
-       sub     r1, r1, #4\n\
-       add     r1, r1, r1\n\
-\n\
-       @ call profiling fixup routine\n\
-       bl      fixup\n\
-\n\
-       @ save the return\n\
-       mov     ip, r0\n\
-\n\
-       @ get arguments and return address back\n\
-       ldmia   sp!, {r0-r3,lr}\n\
-\n\
-       @ jump to the newly found address\n\
-       " BX(ip) "\n\
-\n\
-       .size _dl_runtime_profile, .-_dl_runtime_profile\n\
-       .previous\n\
-");
-#endif //PROF
-
 /* Mask identifying addresses reserved for the user program,
    where the dynamic linker should not map anything.  */
 #define ELF_MACHINE_USER_ADDRESS_MASK  0xf8000000UL
@@ -355,10 +243,10 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rel *reloc,
    Prelinked libraries may use Elf32_Rela though.  */
 #define ELF_MACHINE_NO_RELA defined RTLD_BOOTSTRAP
 
-#ifdef RESOLVE
+#ifdef RESOLVE_MAP
 
 /* Deal with an out-of-range PC24 reloc.  */
-static Elf32_Addr
+auto Elf32_Addr
 fix_bad_pc24 (Elf32_Addr *const reloc_addr, Elf32_Addr value)
 {
   static void *fix_page;
@@ -425,9 +313,8 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
 #endif
     {
       const Elf32_Sym *const refsym = sym;
-      Elf32_Addr value = RESOLVE (&sym, version, r_type);
-      if (sym)
-       value += sym->st_value;
+      struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
+      Elf32_Addr value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;
 
       switch (r_type)
        {
@@ -535,9 +422,8 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
 # ifndef RESOLVE_CONFLICT_FIND_MAP
       const Elf32_Sym *const refsym = sym;
 # endif
-      Elf32_Addr value = RESOLVE (&sym, version, r_type);
-      if (sym)
-       value += sym->st_value;
+      struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
+      Elf32_Addr value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;
 
       switch (r_type)
        {
@@ -637,4 +523,4 @@ elf_machine_lazy_rel (struct link_map *map,
     _dl_reloc_bad_type (map, r_type, 1);
 }
 
-#endif /* RESOLVE */
+#endif /* RESOLVE_MAP */
diff --git a/sysdeps/arm/dl-trampoline.S b/sysdeps/arm/dl-trampoline.S
new file mode 100644 (file)
index 0000000..dc7494f
--- /dev/null
@@ -0,0 +1,214 @@
+/* PLT trampolines.  ARM 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>
+#include <libc-symbols.h>
+
+#if defined(__USE_BX__)
+#define BX(x) bx       x
+#else
+#define BX(x) mov      pc, x
+#endif
+
+       .text
+       .globl _dl_runtime_resolve
+       .type _dl_runtime_resolve, #function
+       cfi_startproc
+       .align 2
+_dl_runtime_resolve:
+       cfi_adjust_cfa_offset (4)
+       cfi_rel_offset (lr, 0)
+
+       @ we get called with
+       @       stack[0] contains the return address from this call
+       @       ip contains &GOT[n+3] (pointer to function)
+       @       lr points to &GOT[2]
+
+       @ Save arguments.  We save r4 to realign the stack.
+       stmdb   sp!,{r0-r4}
+       cfi_adjust_cfa_offset (20)
+       cfi_rel_offset (r0, 0)
+       cfi_rel_offset (r1, 4)
+       cfi_rel_offset (r2, 8)
+       cfi_rel_offset (r3, 12)
+
+       @ get pointer to linker struct
+       ldr     r0, [lr, #-4]
+
+       @ prepare to call _dl_fixup()
+       @ change &GOT[n+3] into 8*n        NOTE: reloc are 8 bytes each
+       sub     r1, ip, lr
+       sub     r1, r1, #4
+       add     r1, r1, r1
+
+       @ call fixup routine
+       bl      _dl_fixup
+
+       @ save the return
+       mov     ip, r0
+
+       @ get arguments and return address back.  We restore r4
+       @ only to realign the stack.
+       ldmia   sp!, {r0-r4,lr}
+       cfi_adjust_cfa_offset (-24)
+
+       @ jump to the newly found address
+       BX(ip)
+
+       cfi_endproc
+       .size _dl_runtime_resolve, .-_dl_runtime_resolve
+
+       .globl _dl_runtime_profile
+       .type _dl_runtime_profile, #function
+       cfi_startproc
+       .align 2
+_dl_runtime_profile:
+       cfi_adjust_cfa_offset (4)
+       cfi_rel_offset (lr, 0)
+
+       @ we get called with
+       @       stack[0] contains the return address from this call
+       @       ip contains &GOT[n+3] (pointer to function)
+       @       lr points to &GOT[2]
+
+       @ Stack layout:
+       @ 212 - saved lr
+       @ 208 - framesize returned from pltenter
+       @ 16 - La_arm_regs
+       @ 8 - Saved two arguments to _dl_profile_fixup
+       @ 4 - Saved result of _dl_profile_fixup
+       @ 0 - outgoing argument to _dl_profile_fixup
+       @ For now, we only save the general purpose registers.
+
+       sub     sp, sp, #196
+       cfi_adjust_cfa_offset (196)
+       stmia   sp, {r0-r3}
+       cfi_rel_offset (r0, 0)
+       cfi_rel_offset (r1, 4)
+       cfi_rel_offset (r2, 8)
+       cfi_rel_offset (r3, 12)
+
+       sub     sp, sp, #16
+       cfi_adjust_cfa_offset (16)
+
+       @ Save sp and lr.
+       add     r0, sp, #216
+       str     r0, [sp, #32]
+       ldr     r2, [sp, #212]
+       str     r2, [sp, #36]
+
+       @ get pointer to linker struct
+       ldr     r0, [lr, #-4]
+
+       @ prepare to call _dl_profile_fixup()
+       @ change &GOT[n+3] into 8*n        NOTE: reloc are 8 bytes each
+       sub     r1, ip, lr
+       sub     r1, r1, #4
+       add     r1, r1, r1
+
+       @ Save these two arguments for pltexit.
+       add     r3, sp, #8
+       stmia   r3!, {r0,r1}
+
+       @ Set up extra args for _dl_profile_fixup.
+       @ r2 and r3 are already loaded.
+       add     ip, sp, #208
+       str     ip, [sp, #0]
+
+       @ call profiling fixup routine
+       bl      _dl_profile_fixup
+
+       @ The address to call is now in r0.
+
+       @ Check whether we're wrapping this function.
+       ldr     ip, [sp, #208]
+       cmp     ip, #0
+       bge     1f
+       cfi_remember_state
+
+       @ save the return
+       mov     ip, r0
+
+       @ get arguments and return address back
+       add     sp, sp, #16
+       cfi_adjust_cfa_offset (-16)
+       ldmia   sp, {r0-r3,sp,lr}
+       cfi_adjust_cfa_offset (-200)
+
+       @ jump to the newly found address
+       BX(ip)
+
+       cfi_restore_state
+1:
+       @ The new frame size is in ip.
+
+       @ New stack layout:
+       @ 268 - saved r7
+       @ 264 - saved result of _dl_profile_fixup
+       @ 72 - La_arm_regs
+       @ 64 - Saved two arguments to _dl_profile_fixup
+       @ 0 - La_arm_retval
+       @ For now, we only save the general purpose registers.
+
+       @ Build the new frame.
+       str     r7, [sp, #212]
+       cfi_rel_offset (r7, 212)
+       sub     r7, sp, #56
+       cfi_def_cfa_register (r7)
+       cfi_adjust_cfa_offset (56)
+       sub     sp, sp, ip
+       bic     sp, sp, #7
+
+       @ Save the _dl_profile_fixup result around the call to memcpy.
+       str     r0, [r7, #264]
+
+       @ Copy the stack arguments.
+       mov     r0, sp
+       add     r1, r7, #272
+       mov     r2, ip
+       bl      memcpy
+
+       @ Call the function.
+       add     ip, r7, #72
+       ldmia   ip, {r0-r3}
+       ldr     ip, [r7, #264]
+       mov     lr, pc
+       BX(ip)
+       stmia   r7, {r0-r3}
+
+       @ Call pltexit.
+       add     ip, r7, #64
+       ldmia   ip, {r0,r1}
+       add     r2, r7, #72
+       add     r3, r7, #0
+       bl      _dl_call_pltexit
+
+       @ Return to caller.
+       ldmia   r7, {r0-r3}
+       mov     sp, r7
+       cfi_def_cfa_register (sp)
+       ldr     r7, [sp, #268]
+       ldr     lr, [sp, #92]
+       add     sp, sp, #272
+       cfi_adjust_cfa_offset (-272)
+       BX(lr)
+
+       cfi_endproc
+       .size _dl_runtime_resolve, .-_dl_runtime_resolve
+       .previous