mirror of
https://sourceware.org/git/glibc.git
synced 2024-12-04 19:00:09 +00:00
219 lines
4.8 KiB
ArmAsm
219 lines
4.8 KiB
ArmAsm
/* PLT trampolines. ARM version.
|
|
Copyright (C) 2005, 2010 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_sections .debug_frame
|
|
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
|
|
|
|
#ifndef PROF
|
|
.globl _dl_runtime_profile
|
|
.type _dl_runtime_profile, #function
|
|
.cfi_sections .debug_frame
|
|
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_profile, .-_dl_runtime_profile
|
|
#endif
|
|
.previous
|