cprt0.as 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /* This is the canonical entry point, usually the first thing in the text
  2. segment. The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry
  3. point runs, most registers' values are unspecified, except for:
  4. %rdx Contains a function pointer to be registered with `atexit'.
  5. This is how the dynamic linker arranges to have DT_FINI
  6. functions called for shared libraries that have been loaded
  7. before this code runs.
  8. %rsp The stack contains the arguments and environment:
  9. 0(%rsp) argc
  10. 8(%rsp) argv[0]
  11. ...
  12. (8*argc)(%rsp) NULL
  13. (8*(argc+1))(%rsp) envp[0]
  14. ...
  15. NULL
  16. */
  17. .text
  18. .globl _start
  19. .type _start,@function
  20. _start:
  21. /* Clear the frame pointer. The ABI suggests this be done, to mark
  22. the outermost frame obviously. */
  23. xorq %rbp, %rbp
  24. /* Extract the arguments as encoded on the stack and set up
  25. the arguments for __libc_start_main (int (*main) (int, char **, char **),
  26. int argc, char *argv,
  27. void (*init) (void), void (*fini) (void),
  28. void (*rtld_fini) (void), void *stack_end).
  29. The arguments are passed via registers and on the stack:
  30. main: %rdi
  31. argc: %rsi
  32. argv: %rdx
  33. init: %rcx
  34. fini: %r8
  35. rtld_fini: %r9
  36. stack_end: stack. */
  37. movq %rdx, %r9 /* Address of the shared library termination
  38. function. */
  39. popq %rsi /* Pop the argument count. */
  40. movq %rsp, %rdx /* argv starts just at the current stack top. */
  41. movq operatingsystem_parameter_argc@GOTPCREL(%rip),%rax
  42. movq %rsi,(%rax)
  43. movq operatingsystem_parameter_argv@GOTPCREL(%rip),%rax
  44. movq %rsp,(%rax) /* argv starts just at the current stack top. */
  45. leaq 8(,%rsi,8),%rax
  46. addq %rsp,%rax
  47. movq operatingsystem_parameter_envp@GOTPCREL(%rip),%rcx
  48. movq %rax,(%rcx)
  49. /* Align the stack to a 16 byte boundary to follow the ABI. */
  50. andq $~15, %rsp
  51. pushq %rax /* Push garbage because we push 8 more bytes. */
  52. /* Provide the highest stack address to the user code (for stacks
  53. which grow downwards). */
  54. pushq %rsp
  55. /* Pass address of our own entry points to .fini and .init. */
  56. movq _init_dummy@GOTPCREL(%rip), %rcx
  57. movq _fini_dummy@GOTPCREL(%rip), %r8
  58. movq main_stub@GOTPCREL(%rip), %rdi
  59. /* Call the user's main function, and exit with its value.
  60. But let the libc call main. */
  61. call __libc_start_main@PLT
  62. hlt /* Crash if somehow `exit' does return. */
  63. /* fake main routine which will be run from libc */
  64. .globl main_stub
  65. .type main_stub,@function
  66. main_stub:
  67. /* save return address */
  68. popq %rax
  69. // stack alignment
  70. pushq %rax
  71. movq ___fpc_ret_rbp@GOTPCREL(%rip),%rcx
  72. movq %rbp,(%rcx)
  73. movq ___fpc_ret@GOTPCREL(%rip),%rcx
  74. movq %rax,(%rcx)
  75. pushq %rax
  76. /* Save initial stackpointer */
  77. movq __stkptr@GOTPCREL(%rip),%rax
  78. movq %rsp,(%rax)
  79. /* start the program */
  80. xorq %rbp,%rbp
  81. call PASCALMAIN@PLT
  82. hlt
  83. .size main_stub,.-main_stub
  84. .globl _haltproc
  85. .type _haltproc,@function
  86. _haltproc:
  87. movl %edi,%eax
  88. /* return to libc */
  89. movq ___fpc_ret_rbp@GOTPCREL(%rip),%rcx
  90. movq (%rcx),%rbp
  91. movq ___fpc_ret@GOTPCREL(%rip),%rcx
  92. movq (%rcx),%rdx
  93. pushq %rdx
  94. ret
  95. .size _haltproc,.-_haltproc
  96. .globl _init_dummy
  97. .type _init_dummy, @function
  98. _init_dummy:
  99. ret
  100. .size _init_dummy,.-_init_dummy
  101. .globl _fini_dummy
  102. .type _fini_dummy, @function
  103. _fini_dummy:
  104. ret
  105. .size _fini_dummy,.-_fini_dummy
  106. /* Define a symbol for the first piece of initialized data. */
  107. .data
  108. .globl __data_start
  109. __data_start:
  110. .long 0
  111. .weak data_start
  112. data_start = __data_start
  113. .globl ___fpc_brk_addr /* heap management */
  114. .type ___fpc_brk_addr,@object
  115. .size ___fpc_brk_addr,8
  116. ___fpc_brk_addr:
  117. .quad 0
  118. ___fpc_ret: /* return address to libc */
  119. .quad 0
  120. ___fpc_ret_rbp:
  121. .quad 0
  122. .bss
  123. .comm __stkptr,8
  124. .comm operatingsystem_parameter_envp,8
  125. .comm operatingsystem_parameter_argc,8
  126. .comm operatingsystem_parameter_argv,8
  127. /* We need this stuff to make gdb behave itself, otherwise
  128. gdb will chokes with SIGILL when trying to debug apps.
  129. */
  130. .section ".note.ABI-tag", "a"
  131. .align 4
  132. .long 1f - 0f
  133. .long 3f - 2f
  134. .long 1
  135. 0: .asciz "GNU"
  136. 1: .align 4
  137. 2: .long 0
  138. .long 2,4,0
  139. 3: .align 4
  140. .section .note.GNU-stack,"",@progbits