ebf8934652
On rela architectures GNU BFD ld and gold store the relocation addend in GOT entries (in addition to the relocation's r_addend field). rtld previously relied on this to access its own _DYNAMIC symbol in order to apply its own relocations. However, recording addends in the GOT is not specified by the ABI, and some versions of LLVM's LLD linker leave the GOT uninitialized on rela architectures. BFD ld does not populate the GOT on sparc64, and sparc64 rtld has a machine-dependent rtld_dynamic_addr() function that returns the _DYNAMIC address. Use the same approach on amd64, obtaining the %rip- relative _DYNAMIC address following a suggestion from Rafael Espíndola. Architectures other than amd64 should be addressed in future work. PR: 214972 Reviewed by: kib MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D9180
172 lines
5.2 KiB
ArmAsm
172 lines
5.2 KiB
ArmAsm
/*-
|
|
* Copyright 1996-1998 John D. Polstra.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* $FreeBSD$
|
|
*/
|
|
|
|
.text
|
|
.align 4
|
|
.globl .rtld_start
|
|
.type .rtld_start,@function
|
|
.rtld_start:
|
|
xorq %rbp,%rbp # Clear frame pointer for good form
|
|
subq $24,%rsp # A place to store exit procedure addr
|
|
movq %rdi,%r12
|
|
movq %rsp,%rsi # save address of exit proc
|
|
movq %rsp,%rdx # construct address of obj_main
|
|
addq $8,%rdx
|
|
call _rtld # Call rtld(sp); returns entry point
|
|
popq %rsi # Get exit procedure address
|
|
movq %r12,%rdi # *ap
|
|
/*
|
|
* At this point, %rax contains the entry point of the main program, and
|
|
* %rdx contains a pointer to a termination function that should be
|
|
* registered with atexit(). (crt1.o registers it.)
|
|
*/
|
|
.globl .rtld_goto_main
|
|
.rtld_goto_main: # This symbol exists just to make debugging easier.
|
|
jmp *%rax # Enter main program
|
|
|
|
|
|
/*
|
|
* Binder entry point. Control is transferred to here by code in the PLT.
|
|
* On entry, there are two arguments on the stack. In ascending address
|
|
* order, they are (1) "obj", a pointer to the calling object's Obj_Entry,
|
|
* and (2) "reloff", the byte offset of the appropriate relocation entry
|
|
* in the PLT relocation table.
|
|
*
|
|
* We are careful to preserve all registers, even the caller-save
|
|
* registers. That is because this code may be invoked by low-level
|
|
* assembly-language code that is not ABI-compliant.
|
|
*
|
|
* Stack map:
|
|
* reloff 0x60
|
|
* obj 0x58
|
|
* spare 0x50
|
|
* rflags 0x48
|
|
* rax 0x40
|
|
* rdx 0x38
|
|
* rcx 0x30
|
|
* rsi 0x28
|
|
* rdi 0x20
|
|
* r8 0x18
|
|
* r9 0x10
|
|
* r10 0x8
|
|
* r11 0x0
|
|
*/
|
|
.align 4
|
|
.globl _rtld_bind_start
|
|
.type _rtld_bind_start,@function
|
|
_rtld_bind_start:
|
|
.cfi_startproc
|
|
.cfi_adjust_cfa_offset 16
|
|
subq $8,%rsp
|
|
.cfi_adjust_cfa_offset 8
|
|
pushfq # Save rflags
|
|
.cfi_adjust_cfa_offset 8
|
|
pushq %rax # Save %rax
|
|
.cfi_adjust_cfa_offset 8
|
|
.cfi_offset %rax,-32
|
|
pushq %rdx # Save %rdx
|
|
.cfi_adjust_cfa_offset 8
|
|
.cfi_offset %rdx,-40
|
|
pushq %rcx # Save %rcx
|
|
.cfi_adjust_cfa_offset 8
|
|
.cfi_offset %rcx,-48
|
|
pushq %rsi # Save %rsi
|
|
.cfi_adjust_cfa_offset 8
|
|
.cfi_offset %rsi,-56
|
|
pushq %rdi # Save %rdi
|
|
.cfi_adjust_cfa_offset 8
|
|
.cfi_offset %rdi,-64
|
|
pushq %r8 # Save %r8
|
|
.cfi_adjust_cfa_offset 8
|
|
.cfi_offset %r8,-72
|
|
pushq %r9 # Save %r9
|
|
.cfi_adjust_cfa_offset 8
|
|
.cfi_offset %r9,-80
|
|
pushq %r10 # Save %r10
|
|
.cfi_adjust_cfa_offset 8
|
|
.cfi_offset %r10,-88
|
|
pushq %r11 # Save %r11
|
|
.cfi_adjust_cfa_offset 8
|
|
.cfi_offset %r11,-96
|
|
|
|
movq 0x58(%rsp),%rdi # Fetch obj argument
|
|
movq 0x60(%rsp),%rsi # Fetch reloff argument
|
|
leaq (%rsi,%rsi,2),%rsi # multiply by 3
|
|
leaq (,%rsi,8),%rsi # now 8, for 24 (sizeof Elf_Rela)
|
|
|
|
call _rtld_bind # Transfer control to the binder
|
|
/* Now %rax contains the entry point of the function being called. */
|
|
|
|
movq %rax,0x60(%rsp) # Store target over reloff argument
|
|
popq %r11 # Restore %r11
|
|
.cfi_adjust_cfa_offset -8
|
|
.cfi_restore %r11
|
|
popq %r10 # Restore %r10
|
|
.cfi_adjust_cfa_offset -8
|
|
.cfi_restore %r10
|
|
popq %r9 # Restore %r9
|
|
.cfi_adjust_cfa_offset -8
|
|
.cfi_restore %r9
|
|
popq %r8 # Restore %r8
|
|
.cfi_adjust_cfa_offset -8
|
|
.cfi_restore %r8
|
|
popq %rdi # Restore %rdi
|
|
.cfi_adjust_cfa_offset -8
|
|
.cfi_restore %rdi
|
|
popq %rsi # Restore %rsi
|
|
.cfi_adjust_cfa_offset -8
|
|
.cfi_restore %rsi
|
|
popq %rcx # Restore %rcx
|
|
.cfi_adjust_cfa_offset -8
|
|
.cfi_restore %rcx
|
|
popq %rdx # Restore %rdx
|
|
.cfi_adjust_cfa_offset -8
|
|
.cfi_restore %rdx
|
|
popq %rax # Restore %rax
|
|
.cfi_adjust_cfa_offset -8
|
|
.cfi_restore %rax
|
|
popfq # Restore rflags
|
|
.cfi_adjust_cfa_offset -8
|
|
leaq 16(%rsp),%rsp # Discard spare, obj, do not change rflags
|
|
ret # "Return" to target address
|
|
.cfi_endproc
|
|
.size _rtld_bind_start, . - _rtld_bind_start
|
|
|
|
.align 4
|
|
.globl rtld_dynamic_addr
|
|
.type rtld_dynamic_addr,@function
|
|
rtld_dynamic_addr:
|
|
.cfi_startproc
|
|
.weak _DYNAMIC
|
|
.hidden _DYNAMIC
|
|
lea _DYNAMIC(%rip),%rax
|
|
ret
|
|
.cfi_endproc
|
|
.size rtld_dynamic_addr, . - rtld_dynamic_addr
|
|
|
|
.section .note.GNU-stack,"",%progbits
|