@@ -221,8 +221,14 @@ static void swift::enumerateUnsafeArgv(const F& body) { }
221
221
// we don't need to take advantage of that here and can stick to things that
222
222
// are defined in the ABI specs.)
223
223
224
- // We'll need this in a minute
225
- extern char **environ;
224
+ #include < unistd.h>
225
+
226
+ #define DEBUG_ARGVGRABBER 0
227
+ #if DEBUG_ARGVGRABBER
228
+ #define ARGVDEBUG (...) fprintf(stderr, __VA_ARGS__)
229
+ #else
230
+ #define ARGVDEBUG (...)
231
+ #endif
226
232
227
233
namespace {
228
234
@@ -248,8 +254,10 @@ struct ArgvGrabber {
248
254
// Find the stack by looking at /proc/self/maps
249
255
ArgvGrabber::stack ArgvGrabber::findStack (void ) {
250
256
FILE *maps = fopen (" /proc/self/maps" , " r" );
251
- if (!maps)
257
+ if (!maps) {
258
+ ARGVDEBUG (" unable to open maps - %d\n " , errno);
252
259
return stack ();
260
+ }
253
261
254
262
char line[256 ];
255
263
void *base = NULL , *top = NULL ;
@@ -260,34 +268,69 @@ ArgvGrabber::stack ArgvGrabber::findStack(void) {
260
268
//
261
269
// Note that we can't look for [stack], because Rosetta and qemu
262
270
// 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 ;
271
+ //
272
+ // We also need to glom on extra VM ranges after the first one
273
+ // we find, because *sometimes* we end up with an extra range.
274
+ void *lo, *hi;
275
+ if (sscanf (line, " %p-%p" , &lo, &hi) == 2 ) {
276
+ if ((void *)line >= lo && (void *)line < hi) {
277
+ base = lo;
278
+ top = hi;
279
+ found = true ;
280
+ } else if (found && top == lo) {
281
+ top = hi;
282
+ }
267
283
}
268
284
}
269
285
270
286
fclose (maps);
271
287
272
- if (!found)
288
+ if (!found) {
289
+ ARGVDEBUG (" stack not found in maps\n " );
273
290
return stack ();
291
+ }
274
292
275
293
return stack (base, top);
276
294
}
277
295
296
+ #if DEBUG_ARGVGRABBER
297
+ void printMaps () {
298
+ FILE *maps = fopen (" /proc/self/maps" , " r" );
299
+ if (!maps) {
300
+ fprintf (stderr, " unable to open maps - %d\n " , errno);
301
+ return ;
302
+ }
303
+
304
+ char line[256 ];
305
+ while (fgets (line, sizeof (line), maps)) {
306
+ fputs (line, stderr);
307
+ }
308
+
309
+ fclose (maps);
310
+ }
311
+ #endif
312
+
278
313
// Find argv by walking backwards from environ
279
314
void ArgvGrabber::findArgv (ArgvGrabber::stack stack) {
280
- if (!stack.base )
315
+ if (!stack.base ) {
316
+ ARGVDEBUG (" no stack\n " );
281
317
return ;
318
+ }
282
319
283
320
// Check that environ points to the stack
284
321
char **envp = environ;
285
- if ((void *)envp < stack.base || (void *)envp >= stack.top )
322
+ if ((void *)envp < stack.base || (void *)envp >= stack.top ) {
323
+ ARGVDEBUG (" envp = %p, stack is from %p to %p\n " ,
324
+ envp, stack.base , stack.top );
325
+ #if DEBUG_ARGVGRABBER
326
+ printMaps ();
327
+ #endif
286
328
return ;
329
+ }
287
330
288
331
char **ptr = envp - 1 ;
289
332
290
- // We're now pointing at the NULL that terminates argv. Keep going back
333
+ // We're now pointing at the NULL that terminates argv. Keep going back
291
334
// while we're seeing pointers (values greater than envp).
292
335
while ((void *)(ptr - 1 ) > stack.base ) {
293
336
--ptr;
@@ -299,10 +342,20 @@ void ArgvGrabber::findArgv(ArgvGrabber::stack stack) {
299
342
return ;
300
343
}
301
344
}
345
+
346
+ ARGVDEBUG (" didn't find argc\n " );
302
347
}
303
348
304
349
ArgvGrabber::ArgvGrabber () : argv(nullptr ), argc(0 ) {
350
+ ARGVDEBUG (" ***GRABBING ARGV for %d***\n " , getpid ());
305
351
findArgv (findStack ());
352
+ #if DEBUG_ARGVGRABBER
353
+ fprintf (stderr, " ARGV is at %p with count %d\n " , argv, argc);
354
+ for (int i = 0 ; i < argc; ++i) {
355
+ fprintf (stderr, " argv[%d] = \" %s\"\n " , i, argv[i]);
356
+ }
357
+ fprintf (stderr, " ***ARGV GRABBED***\n " );
358
+ #endif
306
359
}
307
360
308
361
ArgvGrabber argvGrabber;
0 commit comments