@@ -172,151 +172,7 @@ static char **swift::getUnsafeArgvArgc(int *outArgLen) {
172172
173173template <typename F>
174174static void swift::enumerateUnsafeArgv (const F& body) { }
175- #elif defined(__linux__)
176- // On Linux, there is no easy way to get the argument vector pointer outside
177- // of the main() function. However, the ABI specifications dictate the layout
178- // of the process's initial stack, which looks something like:
179- //
180- // stack top ----> ┌────────────────────────┐
181- // │ Unspecified │
182- // ┊ ┊
183- // ├┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┤
184- // │ Information block │
185- // │ (argument strings, │
186- // │ environment strings, │
187- // │ auxiliary information) │
188- // ┊ ┊
189- // ├┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┤
190- // │ Unspecified │
191- // ┊ ┊
192- // ├┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┤
193- // │ NULL │
194- // ├┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┤
195- // │ Auxiliary Vector │
196- // ┊ ┊
197- // ├┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┤
198- // │ NULL │
199- // ├┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┤
200- // │ Environment Pointers │
201- // ┊ ┊
202- // environ ------> ├┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┤
203- // │ NULL │
204- // ├┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┤
205- // │ Argument Pointers │
206- // ┊ ┊
207- // ├┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┤
208- // │ Argument Count │
209- // ├┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┤
210- // ┊ ┊
211- //
212- // See https://gitlab.com/x86-psABIs/x86-64-ABI,
213- // https://gitlab.com/x86-psABIs/i386-ABI
214- //
215- // The upshot is that if we can get hold of `environ` before anything has
216- // had a chance to change it, we can find the `argv` array and also the
217- // argument count, `argc`, by walking back up the stack.
218- //
219- // (Note that Linux uses this same layout for all platforms, not just x86-based
220- // ones. It also has a fixed layout for the data at the top of the stack, but
221- // we don't need to take advantage of that here and can stick to things that
222- // are defined in the ABI specs.)
223-
224- // We'll need this in a minute
225- extern char **environ;
226-
227- namespace {
228-
229- struct ArgvGrabber {
230- char **argv;
231- int argc;
232-
233- ArgvGrabber ();
234-
235- private:
236- struct stack {
237- void *base;
238- void *top;
239-
240- stack () : base(nullptr ), top(nullptr ) {}
241- stack (void *b, void *t) : base(b), top(t) {}
242- };
243-
244- stack findStack ();
245- void findArgv (stack s);
246- };
247-
248- // Find the stack by looking at /proc/self/maps
249- ArgvGrabber::stack ArgvGrabber::findStack (void ) {
250- FILE *maps = fopen (" /proc/self/maps" , " r" );
251- if (!maps)
252- return stack ();
253-
254- char line[256 ];
255- void *base = NULL , *top = NULL ;
256- bool found = false ;
257- while (fgets (line, sizeof (line), maps)) {
258- // line is on the stack, so we know we're looking at the right
259- // region if line is between base and top.
260- //
261- // Note that we can't look for [stack], because Rosetta and qemu
262- // set up a separate stack for the emulated code.
263- if (sscanf (line, " %p-%p" , &base, &top) == 2
264- && (void *)line >= base && (void *)line < top) {
265- found = true ;
266- break ;
267- }
268- }
269-
270- fclose (maps);
271-
272- if (!found)
273- return stack ();
274-
275- return stack (base, top);
276- }
277-
278- // Find argv by walking backwards from environ
279- void ArgvGrabber::findArgv (ArgvGrabber::stack stack) {
280- if (!stack.base )
281- return ;
282-
283- // Check that environ points to the stack
284- char **envp = environ;
285- if ((void *)envp < stack.base || (void *)envp >= stack.top )
286- return ;
287-
288- char **ptr = envp - 1 ;
289-
290- // We're now pointing at the NULL that terminates argv. Keep going back
291- // while we're seeing pointers (values greater than envp).
292- while ((void *)(ptr - 1 ) > stack.base ) {
293- --ptr;
294-
295- // The first thing less than envp must be the argc value
296- if ((void *)*ptr < (void *)envp) {
297- argc = (int )(intptr_t )*ptr++;
298- argv = ptr;
299- return ;
300- }
301- }
302- }
303-
304- ArgvGrabber::ArgvGrabber () : argv(nullptr ), argc(0 ) {
305- findArgv (findStack ());
306- }
307-
308- ArgvGrabber argvGrabber;
309-
310- } // namespace
311-
312- static char **swift::getUnsafeArgvArgc (int *outArgLen) {
313- *outArgLen = argvGrabber.argc ;
314- return argvGrabber.argv ;
315- }
316-
317- template <typename F>
318- static void swift::enumerateUnsafeArgv (const F& body) { }
319- #elif defined(__CYGWIN__)
175+ #elif defined(__linux__) || defined(__CYGWIN__)
320176static char **swift::getUnsafeArgvArgc (int *outArgLen) {
321177 return nullptr ;
322178}
0 commit comments