dl-startup.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /*
  2. * Architecture specific code used by dl-startup.c
  3. * Copyright (C) 2016 Waldemar Brodkorb <wbx@uclibc-ng.org>
  4. * Copyright (C) 2018 Kalray Inc.
  5. *
  6. * Ported from GNU libc
  7. * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
  8. */
  9. /* Copyright (C) 1995-2016 Free Software Foundation, Inc.
  10. The GNU C Library is free software; you can redistribute it and/or
  11. modify it under the terms of the GNU Lesser General Public License as
  12. published by the Free Software Foundation; either version 2.1 of the
  13. License, or (at your option) any later version.
  14. The GNU C Library is distributed in the hope that it will be useful,
  15. but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. Lesser General Public License for more details.
  18. You should have received a copy of the GNU Lesser General Public
  19. License along with the GNU C Library; if not, see
  20. <http://www.gnu.org/licenses/>. */
  21. #include <features.h>
  22. /* This is the first bit of code, ever, executed in user space of a dynamically
  23. * linked ELF.
  24. * The kernel jumps on this with the following stack layout:
  25. * argc argument counter (integer)
  26. * argv[0] program name (pointer)
  27. * argv[1..argc-1] program args (pointers)
  28. * NULL
  29. * env[0...N] environment variables (pointers)
  30. * NULL
  31. * auxvt[0...N] Auxiliary Vector Table elements (mixed types)
  32. *
  33. * We should call _dl_start($sp) (the argument should point to the previously
  34. * described memory layout).
  35. *
  36. * Next we should skip N arguments (N == _dl_skip_args).
  37. * Those correspond to the arguments which are consumed by the dynamic loader
  38. * if it is called directly as a program, which is possible when
  39. * __LDSO_STANDALONE_SUPPORT__ is defined.
  40. *
  41. * We eventually end up calling the main executable's _start (from ctr1.S).
  42. * The address of this _start is returned by _dl_start (in $r0).
  43. *
  44. * We should call this with one argument (in $r0): the address of _dl_fini()
  45. */
  46. __asm__("\
  47. .text \n\
  48. .globl _start \n\
  49. .type _start, %function \n\
  50. _start: \n\
  51. copyd $r0 = $sp \n\
  52. copyd $r18 = $sp \n\
  53. andd $sp = $sp, -32 \n\
  54. call _dl_start \n\
  55. ;; \n\
  56. .globl _dl_start_user \n\
  57. .type _dl_start_user, %function \n\
  58. _dl_start_user: \n\
  59. pcrel $r1 = @gotaddr() \n\
  60. copyd $r5 = $r0 \n\
  61. copyd $sp = $r18 \n\
  62. ;; \n\
  63. ld $r2 = @gotoff(_dl_skip_args)[$r1] \n\
  64. addd $r0 = $r1, @gotoff(_dl_fini) \n\
  65. ;; \n\
  66. lwz $r3 = 0[$sp] \n\
  67. ;; \n\
  68. sbfw $r4 = $r2, $r3 \n\
  69. addx8d $sp = $r2, $sp \n\
  70. ;; \n\
  71. sd 0[$sp] = $r4 \n\
  72. icall $r5 \n\
  73. ;; \n\
  74. ");
  75. /* Get a pointer to the argv array. On many platforms this can be just
  76. * the address of the first argument, on other platforms we need to
  77. * do something a little more subtle here. */
  78. #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*)ARGS)+1)
  79. /* Handle relocation of the symbols in the dynamic loader. */
  80. static __always_inline
  81. void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, ElfW(Addr) *reloc_addr,
  82. ElfW(Addr) symbol_addr, ElfW(Addr) load_addr, ElfW(Sym) *sym)
  83. {
  84. switch (ELF_R_TYPE(rpnt->r_info)) {
  85. case R_KVX_NONE:
  86. break;
  87. case R_KVX_JMP_SLOT:
  88. *reloc_addr = symbol_addr + rpnt->r_addend;
  89. break;
  90. case R_KVX_RELATIVE:
  91. *reloc_addr = load_addr + rpnt->r_addend;
  92. break;
  93. default:
  94. _dl_exit(1);
  95. }
  96. }