Skip to content

Commit 8a9b106

Browse files
authored
Merge pull request #71761 from apple/revert-71611-eng/PR-117963394
[WIP] Revert "[CommandLine][Linux] Don't read argv from /proc/self/cmdline."
2 parents 40a0260 + 261bae0 commit 8a9b106

File tree

1 file changed

+1
-145
lines changed

1 file changed

+1
-145
lines changed

stdlib/public/CommandLineSupport/CommandLine.cpp

Lines changed: 1 addition & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -172,151 +172,7 @@ static char **swift::getUnsafeArgvArgc(int *outArgLen) {
172172

173173
template <typename F>
174174
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__)
320176
static char **swift::getUnsafeArgvArgc(int *outArgLen) {
321177
return nullptr;
322178
}

0 commit comments

Comments
 (0)