dl-startup.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Architecture specific code used by dl-startup.c
  4. * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org>
  5. */
  6. asm(
  7. " .text\n"
  8. " .globl _start\n"
  9. " .type _start,%function\n"
  10. "_start:\n"
  11. " @ at start time, all the args are on the stack\n"
  12. " mov r0, sp\n"
  13. " bl _dl_start\n"
  14. " @ returns user entry point in r0\n"
  15. " mov r6, r0\n"
  16. " @ we are PIC code, so get global offset table\n"
  17. " ldr sl, .L_GET_GOT\n"
  18. " add sl, pc, sl\n"
  19. ".L_GOT_GOT:\n"
  20. " @ See if we were run as a command with the executable file\n"
  21. " @ name as an extra leading argument.\n"
  22. " ldr r4, .L_SKIP_ARGS\n"
  23. " ldr r4, [sl, r4]\n"
  24. " @ get the original arg count\n"
  25. " ldr r1, [sp]\n"
  26. " @ subtract _dl_skip_args from it\n"
  27. " sub r1, r1, r4\n"
  28. " @ adjust the stack pointer to skip them\n"
  29. " add sp, sp, r4, lsl #2\n"
  30. " @ get the argv address\n"
  31. " add r2, sp, #4\n"
  32. " @ store the new argc in the new stack location\n"
  33. " str r1, [sp]\n"
  34. " @ compute envp\n"
  35. " add r3, r2, r1, lsl #2\n"
  36. " add r3, r3, #4\n"
  37. "\n\n"
  38. " @ load the finalizer function\n"
  39. " ldr r0, .L_FINI_PROC\n"
  40. " ldr r0, [sl, r0]\n"
  41. " @ jump to the user_s entry point\n"
  42. " mov pc, r6\n"
  43. ".L_GET_GOT:\n"
  44. " .word _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n"
  45. ".L_SKIP_ARGS:\n"
  46. " .word _dl_skip_args(GOTOFF)\n"
  47. ".L_FINI_PROC:\n"
  48. " .word _dl_fini(GOT)\n"
  49. "\n\n"
  50. " .size _start,.-_start\n"
  51. ".previous\n"
  52. );
  53. /* Get a pointer to the argv array. On many platforms this can be just
  54. * the address if the first argument, on other platforms we need to
  55. * do something a little more subtle here. */
  56. #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*)ARGS)+1)
  57. /* Handle relocation of the symbols in the dynamic loader. */
  58. static inline
  59. void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr,
  60. unsigned long symbol_addr, unsigned long load_addr, Elf32_Sym *symtab)
  61. {
  62. switch (ELF32_R_TYPE(rpnt->r_info)) {
  63. case R_ARM_NONE:
  64. break;
  65. case R_ARM_ABS32:
  66. *reloc_addr += symbol_addr;
  67. break;
  68. case R_ARM_PC24:
  69. {
  70. unsigned long addend;
  71. long newvalue, topbits;
  72. addend = *reloc_addr & 0x00ffffff;
  73. if (addend & 0x00800000) addend |= 0xff000000;
  74. newvalue = symbol_addr - (unsigned long)reloc_addr + (addend << 2);
  75. topbits = newvalue & 0xfe000000;
  76. if (topbits != 0xfe000000 && topbits != 0x00000000)
  77. {
  78. #if 0
  79. // Don't bother with this during ldso initilization...
  80. newvalue = fix_bad_pc24(reloc_addr, symbol_addr)
  81. - (unsigned long)reloc_addr + (addend << 2);
  82. topbits = newvalue & 0xfe000000;
  83. if (unlikely(topbits != 0xfe000000 && topbits != 0x00000000))
  84. {
  85. SEND_STDERR("R_ARM_PC24 relocation out of range\n");
  86. _dl_exit(1);
  87. }
  88. #else
  89. SEND_STDERR("R_ARM_PC24 relocation out of range\n");
  90. _dl_exit(1);
  91. #endif
  92. }
  93. newvalue >>= 2;
  94. symbol_addr = (*reloc_addr & 0xff000000) | (newvalue & 0x00ffffff);
  95. *reloc_addr = symbol_addr;
  96. break;
  97. }
  98. case R_ARM_GLOB_DAT:
  99. case R_ARM_JUMP_SLOT:
  100. *reloc_addr = symbol_addr;
  101. break;
  102. case R_ARM_RELATIVE:
  103. *reloc_addr += load_addr;
  104. break;
  105. case R_ARM_COPY:
  106. break;
  107. default:
  108. SEND_STDERR("Unsupported relocation type\n");
  109. _dl_exit(1);
  110. }
  111. }
  112. /* Transfer control to the user's application, once the dynamic loader is
  113. * done. This routine has to exit the current function, then call the
  114. * _dl_elf_main function. */
  115. #define START() return _dl_elf_main;