dl-startup.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /*
  2. * Copyright (C) 2016 Andes Technology, Inc.
  3. * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
  4. */
  5. /* Need bootstrap relocations */
  6. #define ARCH_NEEDS_BOOTSTRAP_RELOCS
  7. __asm__("\
  8. .text\n\
  9. .globl _start\n\
  10. .globl _dl_start\n\
  11. .globl _dl_start_user\n\
  12. .type _start,#function\n\
  13. .type _dl_start,#function\n\
  14. .type _dl_start_user,#function\n\
  15. .align 4\n\
  16. .pic\n\
  17. _start:\n\
  18. ! we are PIC code, so get global offset table\n\
  19. mfusr $r15, $PC \n\
  20. sethi $gp, HI20(_GLOBAL_OFFSET_TABLE_ + 4)\n\
  21. ori $gp, $gp, LO12(_GLOBAL_OFFSET_TABLE_ + 8)\n\
  22. add $gp, $r15, $gp\n\
  23. \n\
  24. ! at start time, all the args are on the stack\n\
  25. addi $r0, $sp, 0\n\
  26. ! adjust stack\n\
  27. !addi $sp, $sp, -24\n\
  28. bal _dl_start@PLT\n\
  29. ! save user entry point in r6\n\
  30. addi $r6, $r0, 0\n\
  31. ! adjust sp and reload registers\n\
  32. !addi $sp, $sp, 24\n\
  33. \n\
  34. _dl_start_user:\n\
  35. ! See if we were run as a command with the executable file\n\
  36. ! name as an extra leading argument.\n\
  37. ! skip these arguments\n\
  38. l.w $r2, _dl_skip_args@GOTOFF ! args to skip\n\
  39. lwi $r0, [$sp+0] ! original argc\n\
  40. slli $r1, $r2, 2 ! offset for new sp\n\
  41. add $sp, $sp, $r1 ! adjust sp to skip args\n\
  42. sub $r0, $r0, $r2 ! set new argc\n\
  43. swi $r0, [$sp+0] ! save new argc\n\
  44. \n\
  45. ! load address of _dl_fini finalizer function\n\
  46. la $r5, _dl_fini@GOTOFF\n\
  47. ! jump to the user_s entry point\n\
  48. jr $r6\n\
  49. .size _dl_start_user, . - _dl_start_user\n\
  50. .previous\n\
  51. ");
  52. #define COPY_UNALIGNED_WORD(swp, twp) \
  53. { \
  54. __typeof (swp) __tmp = __builtin_nds32_unaligned_load_w ((unsigned int*)&swp); \
  55. __builtin_nds32_unaligned_store_w ((unsigned int *)twp, __tmp); \
  56. }
  57. /* Get a pointer to the argv array. On many platforms this can be just
  58. * the address if the first argument, on other platforms we need to
  59. * do something a little more subtle here. */
  60. #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*)ARGS)+1)
  61. /* Handle relocation of the symbols in the dynamic loader. */
  62. static __always_inline
  63. void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr,
  64. unsigned long symbol_addr, unsigned long load_addr, Elf32_Sym *symtab)
  65. {
  66. Elf32_Addr value;
  67. switch (ELF32_R_TYPE(rpnt->r_info)) {
  68. case R_NDS32_NONE:
  69. break;
  70. case R_NDS32_32:
  71. case R_NDS32_GLOB_DAT:
  72. case R_NDS32_JMP_SLOT:
  73. *reloc_addr = symbol_addr + rpnt->r_addend;
  74. break;
  75. case R_NDS32_32_RELA:
  76. value = symbol_addr + rpnt->r_addend;
  77. COPY_UNALIGNED_WORD (value, reloc_addr);
  78. break;
  79. #undef COPY_UNALIGNED_WORD
  80. case R_NDS32_RELATIVE:
  81. *reloc_addr = load_addr + rpnt->r_addend;
  82. break;
  83. default:
  84. SEND_STDERR("Unsupported relocation type\n");
  85. _dl_exit(1);
  86. }
  87. }