@@ -221,8 +221,14 @@ static void swift::enumerateUnsafeArgv(const F& body) { }
221221// we don't need to take advantage of that here and can stick to things that
222222// are defined in the ABI specs.)
223223
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
226232
227233namespace {
228234
@@ -248,8 +254,10 @@ struct ArgvGrabber {
248254// Find the stack by looking at /proc/self/maps
249255ArgvGrabber::stack ArgvGrabber::findStack (void ) {
250256 FILE *maps = fopen (" /proc/self/maps" , " r" );
251- if (!maps)
257+ if (!maps) {
258+ ARGVDEBUG (" unable to open maps - %d\n " , errno);
252259 return stack ();
260+ }
253261
254262 char line[256 ];
255263 void *base = NULL , *top = NULL ;
@@ -260,34 +268,69 @@ ArgvGrabber::stack ArgvGrabber::findStack(void) {
260268 //
261269 // Note that we can't look for [stack], because Rosetta and qemu
262270 // 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+ }
267283 }
268284 }
269285
270286 fclose (maps);
271287
272- if (!found)
288+ if (!found) {
289+ ARGVDEBUG (" stack not found in maps\n " );
273290 return stack ();
291+ }
274292
275293 return stack (base, top);
276294}
277295
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+
278313// Find argv by walking backwards from environ
279314void ArgvGrabber::findArgv (ArgvGrabber::stack stack) {
280- if (!stack.base )
315+ if (!stack.base ) {
316+ ARGVDEBUG (" no stack\n " );
281317 return ;
318+ }
282319
283320 // Check that environ points to the stack
284321 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
286328 return ;
329+ }
287330
288331 char **ptr = envp - 1 ;
289332
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
291334 // while we're seeing pointers (values greater than envp).
292335 while ((void *)(ptr - 1 ) > stack.base ) {
293336 --ptr;
@@ -299,10 +342,20 @@ void ArgvGrabber::findArgv(ArgvGrabber::stack stack) {
299342 return ;
300343 }
301344 }
345+
346+ ARGVDEBUG (" didn't find argc\n " );
302347}
303348
304349ArgvGrabber::ArgvGrabber () : argv(nullptr ), argc(0 ) {
350+ ARGVDEBUG (" ***GRABBING ARGV for %d***\n " , getpid ());
305351 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
306359}
307360
308361ArgvGrabber argvGrabber;
0 commit comments