dl-startup.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /*
  2. * Architecture specific code used by dl-startup.c
  3. *
  4. * Copyright (C) 2005-2007 Atmel Corporation
  5. *
  6. * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
  7. */
  8. /* This is the library loader's main entry point. Let _dl_boot2 do its
  9. * initializations and jump to the application's entry point
  10. * afterwards. */
  11. __asm__(" .text\n"
  12. " .global _start\n"
  13. " .type _start,@function\n"
  14. " .hidden _start\n"
  15. "_start:\n"
  16. /* All arguments are on the stack initially */
  17. " mov r12, sp\n"
  18. " rcall _dl_start\n"
  19. /* Returns user entry point in r12. Save it. */
  20. " mov r0, r12\n"
  21. /* We're PIC, so get the Global Offset Table */
  22. " lddpc r6, .L_GOT\n"
  23. ".L_RGOT:\n"
  24. " rsub r6, pc\n"
  25. /* Adjust argc and argv according to _dl_skip_args */
  26. " ld.w r1, r6[_dl_skip_args@got]\n"
  27. " ld.w r1, r1[0]\n"
  28. " ld.w r2, sp++\n"
  29. " sub r2, r1\n"
  30. " add sp, sp, r1 << 2\n"
  31. " st.w --sp, r2\n"
  32. /* Load the finalizer function */
  33. " ld.w r12, r6[_dl_fini@got]\n"
  34. /* Jump to the user's entry point */
  35. " mov pc, r0\n\n"
  36. " .align 2\n"
  37. ".L_GOT:"
  38. " .long .L_RGOT - _GLOBAL_OFFSET_TABLE_\n"
  39. " .size _start, . - _start\n"
  40. " .previous\n");
  41. /* Get a pointer to the argv array. On many platforms this can be just
  42. * the address of the first argument, on other platforms we need to
  43. * do something a little more subtle here. */
  44. #define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long *)ARGS + 1)
  45. /* We can't call functions before the GOT has been initialized */
  46. #define NO_FUNCS_BEFORE_BOOTSTRAP
  47. /*
  48. * Relocate the GOT during dynamic loader bootstrap. This will add
  49. * the load address to all entries in the GOT, which is necessary
  50. * because the linker doesn't generate R_AVR32_RELATIVE relocs for the
  51. * GOT.
  52. */
  53. static __always_inline
  54. void PERFORM_BOOTSTRAP_GOT(struct elf_resolve *tpnt)
  55. {
  56. Elf32_Addr i, nr_got;
  57. register Elf32_Addr *__r6 __asm__("r6");
  58. Elf32_Addr *got = __r6;
  59. nr_got = tpnt->dynamic_info[DT_AVR32_GOTSZ_IDX] / sizeof(*got);
  60. for (i = 2; i < nr_got; i++)
  61. got[i] += tpnt->loadaddr;
  62. }
  63. #define PERFORM_BOOTSTRAP_GOT(tpnt) PERFORM_BOOTSTRAP_GOT(tpnt)
  64. /* Handle relocation of the symbols in the dynamic loader. */
  65. static __always_inline
  66. void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr,
  67. unsigned long symbol_addr,
  68. unsigned long load_addr, Elf32_Sym *symtab)
  69. {
  70. switch(ELF_R_TYPE(rpnt->r_info)) {
  71. case R_AVR32_NONE:
  72. break;
  73. case R_AVR32_GLOB_DAT:
  74. case R_AVR32_JMP_SLOT:
  75. *reloc_addr = symbol_addr;
  76. break;
  77. case R_AVR32_RELATIVE:
  78. SEND_STDERR_DEBUG("Applying RELATIVE relocation: ");
  79. SEND_ADDRESS_STDERR_DEBUG(load_addr, 0);
  80. SEND_STDERR_DEBUG(" + ");
  81. SEND_ADDRESS_STDERR_DEBUG(rpnt->r_addend, 1);
  82. *reloc_addr = load_addr + rpnt->r_addend;
  83. break;
  84. default:
  85. SEND_STDERR("BOOTSTRAP_RELOC: unhandled reloc_type ");
  86. SEND_NUMBER_STDERR(ELF_R_TYPE(rpnt->r_info), 1);
  87. SEND_STDERR("REL, SYMBOL, LOAD: ");
  88. SEND_ADDRESS_STDERR(reloc_addr, 0);
  89. SEND_STDERR(", ");
  90. SEND_ADDRESS_STDERR(symbol_addr, 0);
  91. SEND_STDERR(", ");
  92. SEND_ADDRESS_STDERR(load_addr, 1);
  93. _dl_exit(1);
  94. }
  95. }