1*d7a24b57Sguenther/* $OpenBSD: ldasm.S,v 1.29 2019/02/03 02:20:36 guenther Exp $ */ 2d3d281f4Smiod 3d3d281f4Smiod/* 4d3d281f4Smiod * Copyright (c) 2013 Miodrag Vallat. 5d3d281f4Smiod * 6d3d281f4Smiod * Permission to use, copy, modify, and distribute this software for any 7d3d281f4Smiod * purpose with or without fee is hereby granted, provided that the above 8d3d281f4Smiod * copyright notice and this permission notice appear in all copies. 9d3d281f4Smiod * 10d3d281f4Smiod * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11d3d281f4Smiod * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12d3d281f4Smiod * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13d3d281f4Smiod * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14d3d281f4Smiod * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15d3d281f4Smiod * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16d3d281f4Smiod * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17d3d281f4Smiod */ 18d3d281f4Smiod/* 19d3d281f4Smiod * Copyright (c) 2006 Dale Rahn 20d3d281f4Smiod * 21d3d281f4Smiod * Redistribution and use in source and binary forms, with or without 22d3d281f4Smiod * modification, are permitted provided that the following conditions 23d3d281f4Smiod * are met: 24d3d281f4Smiod * 1. Redistributions of source code must retain the above copyright 25d3d281f4Smiod * notice, this list of conditions and the following disclaimer. 26d3d281f4Smiod * 2. Redistributions in binary form must reproduce the above copyright 27d3d281f4Smiod * notice, this list of conditions and the following disclaimer in the 28d3d281f4Smiod * documentation and/or other materials provided with the distribution. 29d3d281f4Smiod * 30d3d281f4Smiod * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 31d3d281f4Smiod * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 32d3d281f4Smiod * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33d3d281f4Smiod * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 34d3d281f4Smiod * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35d3d281f4Smiod * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 36d3d281f4Smiod * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 37d3d281f4Smiod * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 38d3d281f4Smiod * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 39d3d281f4Smiod * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 40d3d281f4Smiod * SUCH DAMAGE. 41d3d281f4Smiod * 42d3d281f4Smiod */ 43d3d281f4Smiod 44d3d281f4Smiod#include <machine/asm.h> 45d3d281f4Smiod#include <sys/syscall.h> 46d3d281f4Smiod 47043a04f9Sguenther#define AUX_base 7 48043a04f9Sguenther#define AUX_entry 9 49043a04f9Sguenther 50d3d281f4Smiod/* 51d3d281f4Smiod * ld.so entry point. 52d3d281f4Smiod * On entry: r31 points to the kernel argument struct (argv, argv, environ). 53d3d281f4Smiod * The environment pointers list is followed by an array of AuxInfo 54d3d281f4Smiod * structs filled by the kernel. 55d3d281f4Smiod */ 56d3d281f4SmiodENTRY(_dl_start) 57d3d281f4Smiod /* 58d3d281f4Smiod * Two nop because execution may skip up to two instructions. 59d3d281f4Smiod * See setregs() in the kernel for details. 60d3d281f4Smiod * 61d3d281f4Smiod * Note that I have been hacking m88k for years and still fall 62d3d281f4Smiod * into this trap, every time. -- miod 63d3d281f4Smiod */ 64d3d281f4Smiod or %r0, %r0, %r0 65d3d281f4Smiod or %r0, %r0, %r0 66d3d281f4Smiod 67d3d281f4Smiod /* 68d3d281f4Smiod * Get some room for the contiguous AUX pointers array. 69d3d281f4Smiod */ 70d3d281f4Smiod or %r30, %r31, 0 71043a04f9Sguenther subu %r31, %r31, (4 * (AUX_entry + 1)) 72043a04f9Sguenther 73043a04f9Sguenther /* 74043a04f9Sguenther * Align the stack to a 16 byte boundary. 75043a04f9Sguenther */ 76043a04f9Sguenther clr %r31, %r31, 4<0> 77d3d281f4Smiod 78d3d281f4Smiod /* 79d3d281f4Smiod * Invoke _dl_boot_bind 80d3d281f4Smiod */ 81d3d281f4Smiod or %r2, %r30, 0 | kernel args 82d3d281f4Smiod or %r3, %r31, 0 | array base 83d3d281f4Smiod bsr 1f | the following instruction is skipped 841058c092Sguenther bsr _DYNAMIC | but gives us the pc-relative offset 851058c092Sguenther1: ld %r6, %r1, 0 | fetch branch instruction 861058c092Sguenther mak %r5, %r6, 26<2> | pick branch offset and shift left by 2 871058c092Sguenther addu %r4, %r5, %r1 88d3d281f4Smiod bsr _dl_boot_bind 89d3d281f4Smiod 90d3d281f4Smiod ld %r2, %r30, 0 | argc 91d3d281f4Smiod addu %r6, %r30, 4 + 4 92d3d281f4Smiod lda %r3, %r6[%r2] | envp 93043a04f9Sguenther ld %r4, %r31, 4 * AUX_base| ldoff 94d3d281f4Smiod or %r5, %r31, 0 | array base 95d3d281f4Smiod bsr.n _dl_boot 96d3d281f4Smiod addu %r2, %r30, 4 | argv 97d3d281f4Smiod 98043a04f9Sguenther or %r31, %r30, 0 999408922dSmiod bsr 1f | the following instruction is skipped 1009408922dSmiod bcnd eq0, %r0, _dl_dtors | but gives us the pc-relative offset 101441804d4Saoyama1: ld.h %r5, %r1, 2 | fetch branch offset (low 16 bits) 102a4ce9818Smiod jmp.n %r2 1039408922dSmiod lda %r5, %r1[%r5] | cleanup 104d3d281f4SmiodEND(_dl_start) 105d3d281f4Smiod 106d3d281f4Smiod/* 107d3d281f4Smiod * PLT resolver entry point. 108d3d281f4Smiod * Invoked with the following stack frame: 109d3d281f4Smiod * r31(0x00) zero 110d3d281f4Smiod * r31(0x04) ELF object 111d3d281f4Smiod * r31(0x08) saved r11 112d3d281f4Smiod * r31(0x0c) saved r1 113d3d281f4Smiod * All registers but r1 and r11 must be preserved. The resolver must return 114d3d281f4Smiod * to the resolved address with r1 restored. 115d3d281f4Smiod */ 116d3d281f4Smiod#define OBJECT_OFFSET (4 * 1) 117d3d281f4Smiod#define R11_OFFSET (4 * 2) 118d3d281f4Smiod#define R1_OFFSET (4 * 3) 119d3d281f4Smiod#define PLT_FRAME_SIZE (4 * 4) 120d3d281f4Smiod#define REG_SIZE (4 * 12) 121d3d281f4SmiodENTRY(_dl_bind_start) 122d3d281f4Smiod /* 123d3d281f4Smiod * Preserve caller-saved registers. 124d3d281f4Smiod */ 125d3d281f4Smiod subu %r31, %r31, REG_SIZE 126a4ce9818Smiod st.d %r2, %r31, 4 * 0 127a4ce9818Smiod st.d %r4, %r31, 4 * 2 128a4ce9818Smiod st.d %r6, %r31, 4 * 4 129a4ce9818Smiod st.d %r8, %r31, 4 * 6 130d3d281f4Smiod st %r10, %r31, 4 * 8 131a4ce9818Smiod st.d %r12, %r31, 4 * 10 132d3d281f4Smiod 133d3d281f4Smiod /* 134d3d281f4Smiod * Invoke resolver entry point. 135d3d281f4Smiod */ 136d3d281f4Smiod ld %r2, %r31, REG_SIZE + OBJECT_OFFSET 137d3d281f4Smiod bsr.n _dl_bind 138d3d281f4Smiod ld %r3, %r31, REG_SIZE + R11_OFFSET | reloff 139d3d281f4Smiod 140d3d281f4Smiod /* 141d3d281f4Smiod * Preserve return address. 142d3d281f4Smiod */ 143d3d281f4Smiod or %r11, %r2, %r0 144d3d281f4Smiod 145d3d281f4Smiod /* 146d3d281f4Smiod * Restore caller-saved registers. 147d3d281f4Smiod */ 148a4ce9818Smiod ld.d %r12, %r31, 4 * 10 149d3d281f4Smiod ld %r10, %r31, 4 * 8 150a4ce9818Smiod ld.d %r8, %r31, 4 * 6 151a4ce9818Smiod ld.d %r6, %r31, 4 * 4 152a4ce9818Smiod ld.d %r4, %r31, 4 * 2 153a4ce9818Smiod ld.d %r2, %r31, 4 * 0 154d3d281f4Smiod ld %r1, %r31, REG_SIZE + R1_OFFSET 155d3d281f4Smiod 156a4ce9818Smiod jmp.n %r11 157d3d281f4Smiod addu %r31, %r31, REG_SIZE + PLT_FRAME_SIZE 1584307ecf1SguentherEND(_dl_bind_start) 159d3d281f4Smiod 160c99d8a85SmiodENTRY(_dl_cacheflush) 161c99d8a85Smiod tb0 0, %r0, 451 162*d7a24b57Sguenther or %r0, %r0, %r0 | never hit 163c99d8a85Smiod jmp %r1 164c99d8a85SmiodEND(_dl_cacheflush) 165