Path: blob/main/libexec/rtld-elf/aarch64/rtld_start.S
34884 views
/*-1* Copyright (c) 2014 The FreeBSD Foundation2*3* This software was developed by Andrew Turner under4* sponsorship from the FreeBSD Foundation.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11* 2. Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND16* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE17* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE18* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE19* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL20* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS21* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)22* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT23* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY24* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF25* SUCH DAMAGE.26*/2728#include <machine/asm.h>29#include <sys/elf_common.h>3031ENTRY(.rtld_start)32.cfi_undefined x3033mov x19, x0 /* Put ps_strings in a callee-saved register */3435sub sp, sp, #16 /* Make room for obj_main & exit proc */36.cfi_adjust_cfa_offset 163738mov x1, sp /* exit_proc */39add x2, x1, #8 /* obj_main */40bl _rtld /* Call the loader */41mov x8, x0 /* Backup the entry point */42ldp x2, x1, [sp], #16 /* Load cleanup, obj_main */43.cfi_adjust_cfa_offset 04445mov x0, x19 /* Restore ps_strings */46br x8 /* Jump to the entry point */47END(.rtld_start)4849/*50* sp + 0 = &GOT[x + 3]51* sp + 8 = RA52* x16 = &GOT[2]53* x17 = &_rtld_bind_start54*/55ENTRY(_rtld_bind_start)56mov x17, sp5758/* Save frame pointer and SP */59stp x29, x30, [sp, #-16]!60mov x29, sp61.cfi_def_cfa x29, 1662.cfi_offset x30, -863.cfi_offset x29, -166465/* Save the arguments */66stp x0, x1, [sp, #-16]!67stp x2, x3, [sp, #-16]!68stp x4, x5, [sp, #-16]!69stp x6, x7, [sp, #-16]!70stp x8, xzr, [sp, #-16]!7172/* Save any floating-point arguments */73stp q0, q1, [sp, #-32]!74stp q2, q3, [sp, #-32]!75stp q4, q5, [sp, #-32]!76stp q6, q7, [sp, #-32]!7778/* Calculate reloff */79ldr x2, [x17, #0] /* Get the address of the entry */80sub x1, x2, x16 /* Find its offset */81sub x1, x1, #8 /* Adjust for x16 not being at offset 0 */82/* Each rela item has 3 entriesso we need reloff = 3 * index */83lsl x3, x1, #1 /* x3 = 2 * offset */84add x1, x1, x3 /* x1 = x3 + offset = 3 * offset */8586/* Load obj */87ldr x0, [x16, #-8]8889/* Call into rtld */90bl _rtld_bind9192/* Backup the address to branch to */93mov x16, x09495/* restore the arguments */96ldp q6, q7, [sp], #3297ldp q4, q5, [sp], #3298ldp q2, q3, [sp], #3299ldp q0, q1, [sp], #32100ldp x8, xzr, [sp], #16101ldp x6, x7, [sp], #16102ldp x4, x5, [sp], #16103ldp x2, x3, [sp], #16104ldp x0, x1, [sp], #16105106/* Restore frame pointer */107ldp x29, xzr, [sp], #16108109/* Restore link register saved by the plt code */110ldp xzr, x30, [sp], #16111112/* Call into the correct function */113br x16114END(_rtld_bind_start)115116/*117* struct rel_tlsdesc {118* uint64_t resolver_fnc;119* uint64_t resolver_arg;120*121*122* uint64_t _rtld_tlsdesc_static(struct rel_tlsdesc *);123*124* Resolver function for TLS symbols resolved at load time125*/126ENTRY(_rtld_tlsdesc_static)127ldr x0, [x0, #8]128ret129END(_rtld_tlsdesc_static)130131/*132* uint64_t _rtld_tlsdesc_undef(void);133*134* Resolver function for weak and undefined TLS symbols135*/136ENTRY(_rtld_tlsdesc_undef)137str x1, [sp, #-16]!138.cfi_adjust_cfa_offset 16139140mrs x1, tpidr_el0141ldr x0, [x0, #8]142sub x0, x0, x1143144ldr x1, [sp], #16145.cfi_adjust_cfa_offset -16146ret147END(_rtld_tlsdesc_undef)148149/*150* uint64_t _rtld_tlsdesc_dynamic(struct rel_tlsdesc *);151*152* Resolver function for TLS symbols from dlopen()153*/154ENTRY(_rtld_tlsdesc_dynamic)155/* Save registers used in fast path */156stp x1, x2, [sp, #(-2 * 16)]!157stp x3, x4, [sp, #(1 * 16)]158.cfi_adjust_cfa_offset 2 * 16159.cfi_rel_offset x1, 0160.cfi_rel_offset x2, 8161.cfi_rel_offset x3, 16162.cfi_rel_offset x4, 24163164/* Test fastpath - inlined version of tls_get_addr_common(). */165ldr x1, [x0, #8] /* tlsdesc ptr */166mrs x4, tpidr_el0167ldr x0, [x4] /* DTV pointer */168ldr x2, [x0] /* dtv[0] (generation count) */169ldr x3, [x1] /* tlsdec->dtv_gen */170cmp x2, x3171b.ne 1f /* dtv[0] != tlsdec->dtv_gen */172173ldr w2, [x1, #8] /* tlsdec->tls_index */174add w2, w2, #1175ldr x3, [x0, w2, sxtw #3] /* dtv[tlsdesc->tls_index + 1] */176cbz x3, 1f177178/* Return (dtv[tlsdesc->tls_index + 1] + tlsdesc->tls_offs - tp) */179ldr x2, [x1, #16] /* tlsdec->tls_offs */180add x2, x2, x3181sub x0, x2, x4182/* Restore registers and return */183ldp x3, x4, [sp, #(1 * 16)]184ldp x1, x2, [sp], #(2 * 16)185.cfi_adjust_cfa_offset -2 * 16186ret187188/*189* Slow path190* return(191* tls_get_addr_common(tcb, tlsdesc->tls_index, tlsdesc->tls_offs));192*193*/1941:195/* Save all integer registers */196stp x29, x30, [sp, #-(8 * 16)]!197.cfi_adjust_cfa_offset 8 * 16198.cfi_rel_offset x29, 0199.cfi_rel_offset x30, 8200201mov x29, sp202stp x5, x6, [sp, #(1 * 16)]203stp x7, x8, [sp, #(2 * 16)]204stp x9, x10, [sp, #(3 * 16)]205stp x11, x12, [sp, #(4 * 16)]206stp x13, x14, [sp, #(5 * 16)]207stp x15, x16, [sp, #(6 * 16)]208stp x17, x18, [sp, #(7 * 16)]209.cfi_rel_offset x5, 16210.cfi_rel_offset x6, 24211.cfi_rel_offset x7, 32212.cfi_rel_offset x8, 40213.cfi_rel_offset x9, 48214.cfi_rel_offset x10, 56215.cfi_rel_offset x11, 64216.cfi_rel_offset x12, 72217.cfi_rel_offset x13, 80218.cfi_rel_offset x14, 88219.cfi_rel_offset x15, 96220.cfi_rel_offset x16, 104221.cfi_rel_offset x17, 112222.cfi_rel_offset x18, 120223224/* Find the tls offset */225mov x0, x4 /* tcb */226mov x3, x1 /* tlsdesc ptr */227ldr w1, [x3, #8] /* tlsdec->tls_index */228ldr x2, [x3, #16] /* tlsdec->tls_offs */229bl tls_get_addr_common230mrs x1, tpidr_el0231sub x0, x0, x1232233/* Restore slow patch registers */234ldp x17, x18, [sp, #(7 * 16)]235ldp x15, x16, [sp, #(6 * 16)]236ldp x13, x14, [sp, #(5 * 16)]237ldp x11, x12, [sp, #(4 * 16)]238ldp x9, x10, [sp, #(3 * 16)]239ldp x7, x8, [sp, #(2 * 16)]240ldp x5, x6, [sp, #(1 * 16)]241ldp x29, x30, [sp], #(8 * 16)242.cfi_adjust_cfa_offset -8 * 16243.cfi_restore x29244.cfi_restore x30245246/* Restore fast path registers and return */247ldp x3, x4, [sp, #16]248ldp x1, x2, [sp], #(2 * 16)249.cfi_adjust_cfa_offset -2 * 16250ret251END(_rtld_tlsdesc_dynamic)252253GNU_PROPERTY_AARCH64_FEATURE_1_NOTE(GNU_PROPERTY_AARCH64_FEATURE_1_VAL)254255256