dl-startup.h 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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. void* _dl_boot(void);
  7. /* Overrive the default _dl_boot function, and replace it with a bit of asm.
  8. * Then call the real _dl_boot function, which is now named _dl_boot2. */
  9. asm("" \
  10. " .text\n" \
  11. " .globl _dl_boot\n" \
  12. "_dl_boot:\n" \
  13. " mov r7, sp\n" \
  14. " @ldr r0, [sp], #4\n" \
  15. " mov r0, sp\n" \
  16. " bl _dl_boot2\n" \
  17. " mov r6, r0\n" \
  18. " mov r0, r7\n" \
  19. " mov pc, r6\n" \
  20. );
  21. #define DL_BOOT(X) static __attribute_used__ void* _dl_boot2 (X)
  22. /* Get a pointer to the argv array. On many platforms this can be just
  23. * the address if the first argument, on other platforms we need to
  24. * do something a little more subtle here. */
  25. #define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long*) ARGS)
  26. /* Handle relocation of the symbols in the dynamic loader. */
  27. static inline
  28. void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr,
  29. unsigned long symbol_addr, unsigned long load_addr, Elf32_Sym *symtab)
  30. {
  31. switch (ELF32_R_TYPE(rpnt->r_info)) {
  32. case R_ARM_NONE:
  33. break;
  34. case R_ARM_ABS32:
  35. *reloc_addr += symbol_addr;
  36. break;
  37. case R_ARM_PC24:
  38. {
  39. unsigned long addend;
  40. long newvalue, topbits;
  41. addend = *reloc_addr & 0x00ffffff;
  42. if (addend & 0x00800000) addend |= 0xff000000;
  43. newvalue = symbol_addr - (unsigned long)reloc_addr + (addend << 2);
  44. topbits = newvalue & 0xfe000000;
  45. if (topbits != 0xfe000000 && topbits != 0x00000000)
  46. {
  47. #if 0
  48. // Don't bother with this during ldso initilization...
  49. newvalue = fix_bad_pc24(reloc_addr, symbol_addr)
  50. - (unsigned long)reloc_addr + (addend << 2);
  51. topbits = newvalue & 0xfe000000;
  52. if (unlikely(topbits != 0xfe000000 && topbits != 0x00000000))
  53. {
  54. SEND_STDERR("R_ARM_PC24 relocation out of range\n");
  55. _dl_exit(1);
  56. }
  57. #else
  58. SEND_STDERR("R_ARM_PC24 relocation out of range\n");
  59. _dl_exit(1);
  60. #endif
  61. }
  62. newvalue >>= 2;
  63. symbol_addr = (*reloc_addr & 0xff000000) | (newvalue & 0x00ffffff);
  64. *reloc_addr = symbol_addr;
  65. break;
  66. }
  67. case R_ARM_GLOB_DAT:
  68. case R_ARM_JUMP_SLOT:
  69. *reloc_addr = symbol_addr;
  70. break;
  71. case R_ARM_RELATIVE:
  72. *reloc_addr += load_addr;
  73. break;
  74. case R_ARM_COPY:
  75. break;
  76. default:
  77. SEND_STDERR("Unsupported relocation type\n");
  78. _dl_exit(1);
  79. }
  80. }
  81. /* Transfer control to the user's application, once the dynamic loader is
  82. * done. This routine has to exit the current function, then call the
  83. * _dl_elf_main function. */
  84. #define START() return _dl_elf_main;