@@ -172,151 +172,7 @@ static char **swift::getUnsafeArgvArgc(int *outArgLen) {
172
172
173
173
template <typename F>
174
174
static 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__)
320
176
static char **swift::getUnsafeArgvArgc (int *outArgLen) {
321
177
return nullptr ;
322
178
}
0 commit comments