/*- * 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. */ .text .align 4 .globl .rtld_start .type .rtld_start,@function .rtld_start: .cfi_startproc .cfi_undefined %rip xorq %rbp,%rbp # Clear frame pointer for good form subq $24,%rsp # A place to store exit procedure addr .cfi_def_cfa_offset 32 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 .cfi_def_cfa_offset 24 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 .cfi_endproc /* * 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