diff options
Diffstat (limited to 'ldso/ldso/kvx/dl-startup.h')
-rw-r--r-- | ldso/ldso/kvx/dl-startup.h | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/ldso/ldso/kvx/dl-startup.h b/ldso/ldso/kvx/dl-startup.h new file mode 100644 index 000000000..9784c2345 --- /dev/null +++ b/ldso/ldso/kvx/dl-startup.h @@ -0,0 +1,104 @@ +/* + * Architecture specific code used by dl-startup.c + * Copyright (C) 2016 Waldemar Brodkorb <wbx@uclibc-ng.org> + * Copyright (C) 2018 Kalray Inc. + * + * Ported from GNU libc + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Copyright (C) 1995-2016 Free Software Foundation, Inc. + + 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, see + <http://www.gnu.org/licenses/>. */ + +#include <features.h> + +/* This is the first bit of code, ever, executed in user space of a dynamically + * linked ELF. + * The kernel jumps on this with the following stack layout: + * argc argument counter (integer) + * argv[0] program name (pointer) + * argv[1..argc-1] program args (pointers) + * NULL + * env[0...N] environment variables (pointers) + * NULL + * auxvt[0...N] Auxiliary Vector Table elements (mixed types) + * + * We should call _dl_start($sp) (the argument should point to the previously + * described memory layout). + * + * Next we should skip N arguments (N == _dl_skip_args). + * Those correspond to the arguments which are consumed by the dynamic loader + * if it is called directly as a program, which is possible when + * __LDSO_STANDALONE_SUPPORT__ is defined. + * + * We eventually end up calling the main executable's _start (from ctr1.S). + * The address of this _start is returned by _dl_start (in $r0). + * + * We should call this with one argument (in $r0): the address of _dl_fini() + */ +__asm__("\ +.text \n\ +.globl _start \n\ +.type _start, %function \n\ +_start: \n\ + copyd $r0 = $sp \n\ + copyd $r18 = $sp \n\ + andd $sp = $sp, -32 \n\ + call _dl_start \n\ + ;; \n\ +.globl _dl_start_user \n\ +.type _dl_start_user, %function \n\ +_dl_start_user: \n\ + pcrel $r1 = @gotaddr() \n\ + copyd $r5 = $r0 \n\ + copyd $sp = $r18 \n\ + ;; \n\ + ld $r2 = @gotoff(_dl_skip_args)[$r1] \n\ + addd $r0 = $r1, @gotoff(_dl_fini) \n\ + ;; \n\ + lwz $r3 = 0[$sp] \n\ + ;; \n\ + sbfw $r4 = $r2, $r3 \n\ + addx8d $sp = $r2, $sp \n\ + ;; \n\ + sd 0[$sp] = $r4 \n\ + icall $r5 \n\ + ;; \n\ +"); + +/* Get a pointer to the argv array. On many platforms this can be just + * the address of the first argument, on other platforms we need to + * do something a little more subtle here. */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*)ARGS)+1) + +/* Handle relocation of the symbols in the dynamic loader. */ +static __always_inline +void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, ElfW(Addr) *reloc_addr, + ElfW(Addr) symbol_addr, ElfW(Addr) load_addr, ElfW(Sym) *sym) +{ + switch (ELF_R_TYPE(rpnt->r_info)) { + case R_KVX_NONE: + break; + case R_KVX_JMP_SLOT: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_KVX_RELATIVE: + *reloc_addr = load_addr + rpnt->r_addend; + break; + default: + _dl_exit(1); + } +} |