dl-startup.h 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Architecture specific code used by dl-startup.c
  4. * Copyright (C) 2005 by Erik Andersen <andersen@codepoet.org>
  5. */
  6. /* Perform operation OP with PC-relative SRC as the first operand and
  7. * DST as the second. TMP is available as a temporary if needed. */
  8. #ifdef __mcoldfire__
  9. #define PCREL_OP(OP, SRC, DST, TMP, PC) \
  10. "move.l #" SRC " - ., " TMP "\n\t" OP " (-8, " PC ", " TMP "), " DST
  11. #else
  12. #define PCREL_OP(OP, SRC, DST, TMP, PC) \
  13. OP " " SRC "(" PC "), " DST
  14. #endif
  15. __asm__ ("\
  16. .text\n\
  17. .globl _start\n\
  18. .type _start,@function\n\
  19. .hidden _start\n\
  20. _start:\n\
  21. move.l %sp, -(%sp)\n\
  22. jbsr _dl_start\n\
  23. addq.l #4, %sp\n\
  24. /* FALLTHRU */\n\
  25. \n\
  26. .globl _dl_start_user\n\
  27. .type _dl_start_user,@function\n\
  28. _dl_start_user:\n\
  29. # Save the user entry point address in %a4.\n\
  30. move.l %d0, %a4\n\
  31. # See if we were run as a command with the executable file\n\
  32. # name as an extra leading argument.\n\
  33. " PCREL_OP ("move.l", "_dl_skip_args", "%d0", "%d0", "%pc") "\n\
  34. # Pop the original argument count\n\
  35. move.l (%sp)+, %d1\n\
  36. # Subtract _dl_skip_args from it.\n\
  37. sub.l %d0, %d1\n\
  38. # Adjust the stack pointer to skip _dl_skip_args words.\n\
  39. lea (%sp, %d0*4), %sp\n\
  40. # Push back the modified argument count.\n\
  41. move.l %d1, -(%sp)\n\
  42. # Pass our finalizer function to the user in %a1.\n\
  43. " PCREL_OP ("lea", "_dl_fini", "%a1", "%a1", "%pc") "\n\
  44. # Initialize %fp with the stack pointer.\n\
  45. move.l %sp, %fp\n\
  46. # Jump to the user's entry point.\n\
  47. jmp (%a4)\n\
  48. .size _dl_start_user, . - _dl_start_user\n\
  49. .previous");
  50. /* Get a pointer to the argv array. On many platforms this can be just
  51. * the address of the first argument, on other platforms we need to
  52. * do something a little more subtle here. */
  53. #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1)
  54. /* Handle relocation of the symbols in the dynamic loader. */
  55. static __always_inline
  56. void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr,
  57. unsigned long symbol_addr, unsigned long load_addr, Elf32_Sym *symtab)
  58. {
  59. switch (ELF_R_TYPE(rpnt->r_info))
  60. {
  61. case R_68K_8:
  62. *(char *) reloc_addr = symbol_addr + rpnt->r_addend;
  63. break;
  64. case R_68K_16:
  65. *(short *) reloc_addr = symbol_addr + rpnt->r_addend;
  66. break;
  67. case R_68K_32:
  68. *reloc_addr = symbol_addr + rpnt->r_addend;
  69. break;
  70. case R_68K_PC8:
  71. *(char *) reloc_addr = (symbol_addr + rpnt->r_addend
  72. - (unsigned int) reloc_addr);
  73. break;
  74. case R_68K_PC16:
  75. *(short *) reloc_addr = (symbol_addr + rpnt->r_addend
  76. - (unsigned int) reloc_addr);
  77. break;
  78. case R_68K_PC32:
  79. *reloc_addr = (symbol_addr + rpnt->r_addend
  80. - (unsigned int) reloc_addr);
  81. break;
  82. case R_68K_GLOB_DAT:
  83. case R_68K_JMP_SLOT:
  84. *reloc_addr = symbol_addr;
  85. break;
  86. case R_68K_RELATIVE:
  87. *reloc_addr = ((unsigned int) load_addr +
  88. (rpnt->r_addend ? : *reloc_addr));
  89. break;
  90. default:
  91. _dl_exit (1);
  92. }
  93. }