1 // Mark stack as non-executable
2 #if defined(__linux__) && defined(__ELF__)
3 .section .note.GNU-stack, "", @progbits
9 This function is normally used to implement stack growth using the
10 mechanism devised by Ian Lance Taylor for gccgo, described here:
12 http://gcc.gnu.org/wiki/SplitStacks
14 Each Rust function contains an LLVM-generated prologue that compares the
15 stack space required for the current function to the space remaining in
16 the current stack segment, maintained in a platform-specific TLS slot.
17 The stack limit is strategically maintained by the Rust runtime so that
18 it is always in place whenever a Rust function is running.
20 In Rust, however, we currently do not use __morestack for stack growth
21 purposes. Rather each task has one large stack segment. When this
22 __morestack function is run, we interpret this as a "stack overflow"
23 event rather than an event requiring an allocation of a new stack.
25 In the early days, this implementation did indeed have all of the fiddly
26 bits in order to manage split stacks in the sense of always growing
27 stacks. For posterity, the implementation can be found at commit
28 c8e77d5586aed50821e0b9361b2e24c96ade816c if we ever need to refer back
31 -- The __morestack calling convention --
33 For reasons of efficiency the __morestack calling convention
34 is bizarre. The calling function does not attempt to align the
35 stack for the call, and on x86_64 the arguments to __morestack
36 are passed in scratch registers in order to preserve the
37 original function's arguments.
39 Once __morestack has switched to the new stack, instead of
40 returning, it then calls into the original function, resuming
41 execution at the instruction following the call to
42 __morestack. Thus, when the original function returns it
43 actually returns to __morestack, which then deallocates the
44 stack and returns again to the original function's caller.
48 All this trickery causes hell when it comes time for the
49 unwinder to navigate it's way through this function. What
50 will happen is the original function will be unwound first
51 without any special effort, then the unwinder encounters
52 the __morestack frame, which is sitting just above a
53 tiny fraction of a frame (containing just a return pointer
54 and, on 32-bit, the arguments to __morestack).
56 We deal with this by claiming that little bit of stack
57 is actually part of the __morestack frame, encoded as
58 DWARF call frame instructions (CFI) by .cfi assembler
61 One final complication (that took me a week to figure out)
62 is that OS X 10.6+ uses its own 'compact unwind info',
63 an undocumented format generated by the linker from
64 the DWARF CFI. This compact unwind info doesn't correctly
65 capture the nuance of the __morestack frame, so we need to
66 prevent the linker from attempting to convert its DWARF unwind
72 #if defined(__APPLE__)
73 #define MORESTACK ___morestack
74 #define EXHAUSTED _rust_stack_exhausted
76 #if defined(__linux__) || defined(__FreeBSD__)
77 #define MORESTACK __morestack
78 #define EXHAUSTED rust_stack_exhausted@plt
80 #define MORESTACK ___morestack
81 #define EXHAUSTED _rust_stack_exhausted
87 // FIXME: What about __WIN32__?
88 #if defined(__linux__) || defined(__FreeBSD__)
91 #if defined(__APPLE__)
92 .private_extern MORESTACK
97 .type MORESTACK,@function
103 // This base pointer setup differs from most in that we are
104 // telling the unwinder to consider the Canonical Frame
105 // Address (CFA) for this frame to be the value of the stack
106 // pointer prior to entry to the original function, whereas
107 // the CFA would typically be the value of the stack
108 // pointer prior to entry to this function. This will allow
109 // the unwinder to understand how to skip the tiny partial
110 // frame that the original function created by calling
113 // In practical terms, our CFA is 12 bytes greater than it
114 // would normally be, accounting for the two arguments to
115 // __morestack, and an extra return address.
117 // FIXME(#9854) these cfi directives don't work on windows.
121 #if defined(__APPLE__)
122 // The pattern of the return address being saved twice to the same location
123 // tells the OS X linker that it should not attempt to convert the DWARF
124 // unwind information to the compact format.
129 // The CFA is 20 bytes above the register that it is
130 // associated with for this frame (which will be %ebp)
131 .cfi_def_cfa_offset 20
132 // %ebp is -20 bytes from the CFA
133 .cfi_offset %ebp, -20
135 // Calculate the CFA as an offset from %ebp
136 .cfi_def_cfa_register %ebp
138 // re-align the stack
141 // the exhaustion function guarantees that it can't return