|
21 | 21 | #include "config.h" |
22 | 22 | #include <wtf/StackBounds.h> |
23 | 23 |
|
| 24 | +#include "MainThread.h" |
| 25 | + |
24 | 26 | #if OS(DARWIN) |
25 | 27 |
|
26 | 28 | #include <pthread.h> |
|
46 | 48 |
|
47 | 49 | namespace WTF { |
48 | 50 |
|
| 51 | +#if !CPU(ADDRESS64) |
| 52 | +static std::atomic<void*> bottomOfMainThreadMain = nullptr; |
| 53 | +#endif |
| 54 | + |
| 55 | +void StackBounds::setBottomOfMainThreadMain([[maybe_unused]] void* stack) |
| 56 | +{ |
| 57 | +#if !CPU(ADDRESS64) |
| 58 | + RELEASE_ASSERT(bottomOfMainThreadMain == nullptr); |
| 59 | + bottomOfMainThreadMain = stack; |
| 60 | +#endif |
| 61 | +} |
| 62 | + |
49 | 63 | #if OS(DARWIN) |
50 | 64 |
|
51 | 65 | StackBounds StackBounds::newThreadStackBounds(PlatformThreadHandle thread) |
@@ -135,15 +149,23 @@ StackBounds StackBounds::currentThreadStackBoundsInternal() |
135 | 149 |
|
136 | 150 | static char** oldestEnviron = environ; |
137 | 151 |
|
138 | | - // In 32bit architecture, it is possible that environment variables are having a characters which looks like a pointer, |
139 | | - // and conservative GC will find it as a live pointer. We would like to avoid that to precisely exclude non user stack |
140 | | - // data region from this stack bounds. As the article (https://lwn.net/Articles/631631/) and the elf loader implementation |
141 | | - // explain how Linux main thread stack is organized, environment variables vector is placed on the stack, so we can exclude |
142 | | - // environment variables if we use `environ` global variable as a origin of the stack. |
| 152 | + // On 32bit, it is possible that environment variables and other random data in libc have bytes which look like a pointer, |
| 153 | + // and conservative GC will find it as a live pointer. We would like to avoid that, so we exclude the non-user stack |
| 154 | + // data region from these stack bounds. This article explains how the main thread looks (https://lwn.net/Articles/631631/). |
| 155 | + // |
| 156 | + // First, we exclude environment variables by using `environ` global variable as a origin of the stack. |
143 | 157 | // But `setenv` / `putenv` may alter `environ` variable's content. So we record the oldest `environ` variable content, and use it. |
| 158 | + |
144 | 159 | StackBounds stackBounds { origin, bound }; |
145 | 160 | if (stackBounds.contains(oldestEnviron)) |
146 | 161 | stackBounds = { oldestEnviron, bound }; |
| 162 | + |
| 163 | + // Then, we exclude any greater region based on manual calls to setBottomOfMainThreadMain. |
| 164 | +#if !CPU(ADDRESS64) |
| 165 | + if (stackBounds.contains(bottomOfMainThreadMain)) |
| 166 | + stackBounds = { bottomOfMainThreadMain, bound }; |
| 167 | +#endif |
| 168 | + |
147 | 169 | return stackBounds; |
148 | 170 | } |
149 | 171 | #endif |
|
0 commit comments