gprt0.as 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  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), %r8
  57. movq _fini_dummy@GOTPCREL(%rip), %rcx
  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. /* Initialize gmon */
  77. movq _etext@GOTPCREL(%rip),%rsi
  78. movq _start@GOTPCREL(%rip),%rdi
  79. call monstartup@PLT
  80. movq _mcleanup@GOTPCREL(%rip),%rdi
  81. call atexit@PLT
  82. /* Save initial stackpointer */
  83. movq __stkptr@GOTPCREL(%rip),%rax
  84. movq %rsp,(%rax)
  85. /* start the program */
  86. xorq %rbp,%rbp
  87. call PASCALMAIN@PLT
  88. hlt
  89. .size main_stub,.-main_stub
  90. .globl _haltproc
  91. .type _haltproc,@function
  92. _haltproc:
  93. movq operatingsystem_result@GOTPCREL(%rip),%rax
  94. movzwl (%rax),%eax
  95. /* return to libc */
  96. movq ___fpc_ret_rbp@GOTPCREL(%rip),%rcx
  97. movq (%rcx),%rbp
  98. movq ___fpc_ret@GOTPCREL(%rip),%rcx
  99. movq (%rcx),%rdx
  100. pushq %rdx
  101. ret
  102. .size _haltproc,.-_haltproc
  103. .globl _init_dummy
  104. .type _init_dummy, @function
  105. _init_dummy:
  106. ret
  107. .size _init_dummy,.-_init_dummy
  108. .globl _fini_dummy
  109. .type _fini_dummy, @function
  110. _fini_dummy:
  111. ret
  112. .size _fini_dummy,.-_fini_dummy
  113. /* Define a symbol for the first piece of initialized data. */
  114. .data
  115. .globl __data_start
  116. __data_start:
  117. .long 0
  118. .weak data_start
  119. data_start = __data_start
  120. .globl ___fpc_brk_addr /* heap management */
  121. .type ___fpc_brk_addr,@object
  122. .size ___fpc_brk_addr,8
  123. ___fpc_brk_addr:
  124. .quad 0
  125. ___fpc_ret: /* return address to libc */
  126. .quad 0
  127. ___fpc_ret_rbp:
  128. .quad 0
  129. .bss
  130. .comm __stkptr,8
  131. .comm operatingsystem_parameter_envp,8
  132. .comm operatingsystem_parameter_argc,8
  133. .comm operatingsystem_parameter_argv,8
  134. /* We need this stuff to make gdb behave itself, otherwise
  135. gdb will chokes with SIGILL when trying to debug apps.
  136. */
  137. .section ".note.ABI-tag", "a"
  138. .align 4
  139. .long 1f - 0f
  140. .long 3f - 2f
  141. .long 1
  142. 0: .asciz "GNU"
  143. 1: .align 4
  144. 2: .long 0
  145. .long 2,4,0
  146. 3: .align 4
  147. .section .note.GNU-stack,"",@progbits