This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
ARM fixes for HEAD
- From: Daniel Jacobowitz <drow at false dot org>
- To: libc-alpha at sources dot redhat dot com
- Cc: Mark Mitchell <mark at codesourcery dot com>, Phil Blundell <philb at gnu dot org>
- Date: Fri, 18 Mar 2005 17:21:21 -0500
- Subject: ARM fixes for HEAD
This patch fixes all of the recent problems I could find on ARM glibc.
check-textrel and vismain require binutils fixes that I've sent to
binutils@ just now.
This includes working auditing support, compatibility with recent
kernel headers, and the RESOLVE -> RESOLVE_MAP change.
Tested on arm-linux and the test results are very good. The only
two failures are:
make[1]: *** [/mnt/nbd/check-glibc/stdio-common/tfformat.out] Error 1
make[1]: *** [/mnt/nbd/check-glibc/stdio-common/tst-sprintf.out] Error 1
I didn't get to investigate these two, but they've been around for a
couple of versions now.
Patch look OK?
--
Daniel Jacobowitz
CodeSourcery, LLC
2005-03-18 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.
(ARCH_LA_PLTENTER, ARCH_LA_PLTEXIT): Define.
(elf_machine_rel, elf_machine_rela): Use RESOLVE_MAP.
* sysdeps/generic/ldsodefs.h (struct audit_ifaces): Add ARM entries.
* elf/tst-auditmod1.c: Add ARM definitions.
* sysdeps/unix/sysv/linux/arm/ioperm.c (BUS_ISA): Define for new
kernel headers.
Index: glibc/sysdeps/arm/bits/link.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc/sysdeps/arm/bits/link.h 2005-03-18 00:09:43.000000000 -0500
@@ -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: glibc/sysdeps/unix/sysv/linux/arm/ioperm.c
===================================================================
--- glibc.orig/sysdeps/unix/sysv/linux/arm/ioperm.c 2003-02-20 17:22:35.000000000 -0500
+++ glibc/sysdeps/unix/sysv/linux/arm/ioperm.c 2005-03-18 13:58:20.592031177 -0500
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 1999, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 1999, 2003, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Phil Blundell, based on the Alpha version by
David Mosberger.
@@ -44,6 +44,7 @@
#include <sys/types.h>
#include <sys/mman.h>
+#include <linux/version.h>
#include <asm/page.h>
#include <sys/sysctl.h>
@@ -80,7 +81,7 @@ static struct platform {
* Initialize I/O system. There are several ways to get the information
* we need. Each is tried in turn until one succeeds.
*
- * 1. Sysctl (CTL_BUS, BUS_ISA, ISA_*). This is the preferred method
+ * 1. Sysctl (CTL_BUS, CTL_BUS_ISA, ISA_*). This is the preferred method
* but not all kernels support it.
*
* 2. Read the value (not the contents) of symlink PATH_ARM_SYSTYPE.
@@ -95,6 +96,12 @@ static struct platform {
* values.
*/
+/* The Linux kernel headers renamed this constant between 2.5.26 and
+ 2.5.27. It was backported to 2.4 between 2.4.22 and 2.4.23. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,23)
+# define BUS_ISA CTL_BUS_ISA
+#endif
+
static int
init_iosys (void)
{
Index: glibc/sysdeps/arm/dl-trampoline.S
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ glibc/sysdeps/arm/dl-trampoline.S 2005-03-18 11:32:35.864700065 -0500
@@ -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
Index: glibc/sysdeps/generic/ldsodefs.h
===================================================================
--- glibc.orig/sysdeps/generic/ldsodefs.h 2005-03-17 09:53:35.000000000 -0500
+++ glibc/sysdeps/generic/ldsodefs.h 2005-03-17 11:47:36.000000000 -0500
@@ -195,6 +195,8 @@ struct La_s390_64_regs;
struct La_s390_64_retval;
struct La_ia64_regs;
struct La_ia64_retval;
+struct La_arm_regs;
+struct La_arm_retval;
struct audit_ifaces
{
@@ -251,6 +253,10 @@ struct audit_ifaces
uintptr_t *, struct La_ia64_regs *,
unsigned int *, const char *name,
long int *framesizep);
+ Elf32_Addr (*arm_gnu_pltenter) (Elf32_Sym *, unsigned int, uintptr_t *,
+ uintptr_t *, struct La_arm_regs *,
+ unsigned int *, const char *name,
+ long int *framesizep);
};
union
{
@@ -294,6 +300,9 @@ struct audit_ifaces
uintptr_t *,
const struct La_ia64_regs *,
struct La_ia64_retval *, const char *);
+ unsigned int (*arm_gnu_pltexit) (Elf32_Sym *, unsigned int, uintptr_t *,
+ uintptr_t *, const struct La_arm_regs *,
+ struct La_arm_retval *, const char *);
};
unsigned int (*objclose) (uintptr_t *);
Index: glibc/elf/tst-auditmod1.c
===================================================================
--- glibc.orig/elf/tst-auditmod1.c 2005-03-17 09:53:35.000000000 -0500
+++ glibc/elf/tst-auditmod1.c 2005-03-18 11:34:10.805047834 -0500
@@ -162,6 +162,12 @@ la_symbind64 (Elf64_Sym *sym, unsigned i
# define La_regs La_ia64_regs
# define La_retval La_ia64_retval
# define int_retval lrv_r8
+#elif __arm__
+# define pltenter la_arm_gnu_pltenter
+# define pltext la_arm_gnu_pltexit
+# define La_regs La_arm_regs
+# define La_retval La_arm_retval
+# define int_retval lrv_reg[0]
#else
# error "architecture specific code needed"
#endif
Index: glibc/sysdeps/arm/dl-machine.h
===================================================================
--- glibc.orig/sysdeps/arm/dl-machine.h 2005-03-17 10:25:41.000000000 -0500
+++ glibc/sysdeps/arm/dl-machine.h 2005-03-17 22:33:37.000000000 -0500
@@ -110,7 +110,8 @@ elf_machine_runtime_setup (struct link_m
{
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_m
#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,7 +243,11 @@ elf_machine_plt_value (struct link_map *
Prelinked libraries may use Elf32_Rela though. */
#define ELF_MACHINE_NO_RELA defined RTLD_BOOTSTRAP
-#ifdef RESOLVE
+/* Names of the architecture-specific auditing callback functions. */
+#define ARCH_LA_PLTENTER arm_gnu_pltenter
+#define ARCH_LA_PLTEXIT arm_gnu_pltexit
+
+#ifdef RESOLVE_MAP
/* Deal with an out-of-range PC24 reloc. */
static Elf32_Addr
@@ -425,9 +317,8 @@ elf_machine_rel (struct link_map *map, c
#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 +426,8 @@ elf_machine_rela (struct link_map *map,
# 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 +527,4 @@ elf_machine_lazy_rel (struct link_map *m
_dl_reloc_bad_type (map, r_type, 1);
}
-#endif /* RESOLVE */
+#endif /* RESOLVE_MAP */