cprt0.as 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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 entryinfo@GOTPCREL(%rip),%r10 /* load address of entryinfo variable */
  42. movq %rsi,56(%r10)
  43. movq %rsp,64(%r10) /* argv starts just at the current stack top */
  44. leaq 8(,%rsi,8),%rax
  45. addq %rsp,%rax
  46. movq %rax,72(%r10)
  47. /* Align the stack to a 16 byte boundary to follow the ABI. */
  48. andq $~15, %rsp
  49. pushq %rax /* Push garbage because we push 8 more bytes. */
  50. /* Provide the highest stack address to the user code (for stacks
  51. which grow downwards). */
  52. pushq %rsp
  53. /* Pass address of our own entry points to .fini and .init. */
  54. movq __libc_csu_init@GOTPCREL(%rip), %rcx
  55. movq __libc_csu_fini@GOTPCREL(%rip), %r8
  56. movq main_stub@GOTPCREL(%rip), %rdi
  57. /* Call the user's main function, and exit with its value.
  58. But let the libc call main. */
  59. call __libc_start_main@PLT
  60. hlt /* Crash if somehow `exit' does return. */
  61. /* fake main routine which will be run from libc */
  62. .globl main_stub
  63. .type main_stub,@function
  64. main_stub:
  65. /* save return address */
  66. popq %rax
  67. // stack alignment
  68. pushq %rax
  69. movq ___fpc_ret_rbp@GOTPCREL(%rip),%rcx
  70. movq %rbp,(%rcx)
  71. movq ___fpc_ret@GOTPCREL(%rip),%rcx
  72. movq %rax,(%rcx)
  73. pushq %rax
  74. /* fill the remaining fields of the entry information */
  75. movq entryinfo@GOTPCREL(%rip),%rdi /* load address of entryinfo variable into argument for SysEntry*/
  76. /* Save initial stackpointer */
  77. movq %rsp,80(%rdi)
  78. /* store stack length */
  79. movq __stklen@GOTPCREL(%rip),%rax
  80. movq %rax,88(%rdi)
  81. /* store pointer to _haltproc */
  82. movq _haltproc@GOTPCREL(%rip),%rax
  83. movq %rax,96(%rdi)
  84. /* populate the table pointers */
  85. movq INITFINAL@GOTPCREL(%rip),%rax
  86. movq %rax,(%rdi)
  87. movq FPC_THREADVARTABLES@GOTPCREL(%rip),%rax
  88. movq %rax,8(%rdi)
  89. movq FPC_RESOURCESTRINGTABLES@GOTPCREL(%rip),%rax
  90. movq %rax,16(%rdi)
  91. movq FPC_RESSTRINITTABLES@GOTPCREL(%rip),%rax
  92. movq %rax,24(%rdi)
  93. movq FPC_RESLOCATION@GOTPCREL(%rip),%rax
  94. movq %rax,32(%rdi)
  95. movq PASCALMAIN@GOTPCREL(%rip),%rax
  96. movq %rax,40(%rdi)
  97. /* valgrind_used can stay 0 */
  98. /* start the program */
  99. xorq %rbp,%rbp
  100. call FPC_SysEntry@PLT
  101. hlt
  102. .size main_stub,.-main_stub
  103. .globl _haltproc
  104. .type _haltproc,@function
  105. _haltproc:
  106. movl %edi,%eax
  107. /* return to libc */
  108. movq ___fpc_ret_rbp@GOTPCREL(%rip),%rcx
  109. movq (%rcx),%rbp
  110. movq ___fpc_ret@GOTPCREL(%rip),%rcx
  111. movq (%rcx),%rdx
  112. pushq %rdx
  113. ret
  114. .size _haltproc,.-_haltproc
  115. /* Define a symbol for the first piece of initialized data. */
  116. .data
  117. .globl __data_start
  118. __data_start:
  119. .long 0
  120. .weak data_start
  121. data_start = __data_start
  122. .globl ___fpc_brk_addr /* heap management */
  123. .type ___fpc_brk_addr,@object
  124. .size ___fpc_brk_addr,8
  125. ___fpc_brk_addr:
  126. .quad 0
  127. ___fpc_ret: /* return address to libc */
  128. .quad 0
  129. ___fpc_ret_rbp:
  130. .quad 0
  131. .bss
  132. /* the entry information looks like this:
  133. TEntryInformation = record
  134. InitFinalTable : Pointer; // offset 0
  135. ThreadvarTablesTable : Pointer; // offset 8
  136. ResourceStringTables : Pointer; // offset 16
  137. ResStrInitTables : Pointer; // offset 24
  138. ResLocation : Pointer; // offset 32
  139. PascalMain : Procedure; // offset 40
  140. valgrind_used : boolean; // offset 48
  141. OS : TEntryInformationOS; // offset 56
  142. end;
  143. with TEntryInformationOS being
  144. TEntryInformationOS = record
  145. argc: longint; // offset 56
  146. argv: ppchar; // offset 64
  147. envp: ppchar; // offset 72
  148. stkptr: pointer; // offset 80
  149. stklen: sizeuint; // offset 88
  150. haltproc: procedure(e:longint);cdecl; // offset 96
  151. end;
  152. The size of TEntryInformationOS including padding is 5 * sizeof(Pointer) = 40
  153. The size of TEntryInformation including padding without OS is 8 * sizeof(Pointer) = 64
  154. Thus the total size of TEntryInformation including padding is 104
  155. */
  156. .comm entryinfo,104
  157. /* We need this stuff to make gdb behave itself, otherwise
  158. gdb will chokes with SIGILL when trying to debug apps.
  159. */
  160. .section ".note.ABI-tag", "a"
  161. .align 4
  162. .long 1f - 0f
  163. .long 3f - 2f
  164. .long 1
  165. 0: .asciz "GNU"
  166. 1: .align 4
  167. 2: .long 0
  168. .long 2,4,0
  169. 3: .align 4
  170. .section .note.GNU-stack,"",@progbits