From: Phil Blundell Date: Fri, 10 Jun 2005 11:33:52 +0000 (+0000) Subject: 2005-05-09 Daniel Jacobowitz X-Git-Tag: upstream/2.30~10627^2~1039 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=849e84dde3da78ba1462106329a64baf7eb68e42;p=external%2Fglibc.git 2005-05-09 Daniel Jacobowitz Mark Mitchell * 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. --- diff --git a/ChangeLog.arm b/ChangeLog.arm index e36328b..360b06f 100644 --- a/ChangeLog.arm +++ b/ChangeLog.arm @@ -1,6 +1,18 @@ 2005-05-09 Daniel Jacobowitz Mark Mitchell + * 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 + Mark Mitchell + * sysdeps/unix/sysv/linux/arm/ioperm.c (BUS_ISA): Define for new kernel headers. diff --git a/sysdeps/arm/bits/link.h b/sysdeps/arm/bits/link.h index e69de29..8dbd2c7 100644 --- a/sysdeps/arm/bits/link.h +++ b/sysdeps/arm/bits/link.h @@ -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 directly; use 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 diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h index 0fe47b2..abff153 100644 --- a/sysdeps/arm/dl-machine.h +++ b/sysdeps/arm/dl-machine.h @@ -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 index 0000000..dc7494f --- /dev/null +++ b/sysdeps/arm/dl-trampoline.S @@ -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 +#include + +#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