@@ -1311,6 +1311,60 @@ rtld_setup_main_map (struct link_map *main_map)
return has_interp;
}
+#ifdef DL_NEED_START_ARGS_ADJUST
+static void
+_dl_start_args_adjust (void)
+{
+ void **sp;
+ void **p;
+ long argc;
+ char **argv;
+ ElfW(auxv_t) *auxv;
+
+ if (_dl_skip_args == 0)
+ return;
+
+ sp = _dl_start_argptr;
+
+ /* Adjust argc on stack. */
+ argc = (long) sp[0] - _dl_skip_args;
+ sp[0] = (void *) argc;
+
+ argv = (char **) (sp + 1); /* Necessary aliasing violation. */
+ p = sp + _dl_skip_args;
+ /* Shuffle argv down. */
+ do
+ *++sp = *++p;
+ while (*p != NULL);
+
+ /* Shuffle envp down. */
+ do
+ *++sp = *++p;
+ while (*p != NULL);
+
+ auxv = (ElfW(auxv_t) *) (sp + 1); /* Necessary aliasing violation. */
+ /* Shuffle auxv down. */
+ void *a, *b; /* Use a pair of pointers for an auxv entry. */
+ unsigned long a_type;
+ do
+ {
+ a_type = ((ElfW(auxv_t) *) (p + 1))->a_type;
+ a = *++p;
+ b = *++p;
+ *++sp = a;
+ *++sp = b;
+ }
+ while (a_type != AT_NULL);
+
+ /* Update globals in rtld. */
+ _dl_argv = argv;
+ _environ = argv + argc + 1;
+ GLRO(dl_auxv) = auxv;
+ /* No longer need to skip args. */
+ _dl_skip_args = 0;
+}
+#endif
+
static void
dl_main (const ElfW(Phdr) *phdr,
ElfW(Word) phnum,
@@ -1615,6 +1669,10 @@ dl_main (const ElfW(Phdr) *phdr,
/* Set the argv[0] string now that we've processed the executable. */
if (argv0 != NULL)
_dl_argv[0] = argv0;
+#ifdef DL_NEED_START_ARGS_ADJUST
+ /* Adjust arguments for the application entry point. */
+ _dl_start_args_adjust ();
+#endif
}
else
{
@@ -20,6 +20,6 @@
/* _dl_argv cannot be attribute_relro, because _dl_start_user
might write into it after _dl_start returns. */
-#define DL_ARGV_NOT_RELRO 1
+#define DL_NEED_START_ARGS_ADJUST 1
#define DL_EXTERN_PROTECTED_DATA
@@ -785,6 +785,9 @@ extern unsigned int _dl_skip_args attribute_hidden
attribute_relro
# endif
;
+# ifdef DL_NEED_START_ARGS_ADJUST
+extern void **_dl_start_argptr attribute_hidden attribute_relro;
+# endif
#endif
#define rtld_progname _dl_argv[0]
@@ -58,6 +58,12 @@ void *__libc_stack_end attribute_relro = NULL;
rtld_hidden_data_def(__libc_stack_end)
void *_dl_random attribute_relro = NULL;
+#ifdef DL_NEED_START_ARGS_ADJUST
+/* Original sp at ELF entry, used when rtld is executed explicitly
+ and needs to adjust arg components for the actual application. */
+void **_dl_start_argptr attribute_hidden attribute_relro = NULL;
+#endif
+
#ifndef DL_STACK_END
# define DL_STACK_END(cookie) ((void *) (cookie))
#endif
@@ -114,6 +120,10 @@ _dl_sysdep_start (void **start_argptr,
__brk (0); /* Initialize the break. */
+#ifdef DL_NEED_START_ARGS_ADJUST
+ _dl_start_argptr = start_argptr;
+#endif
+
#ifdef DL_PLATFORM_INIT
DL_PLATFORM_INIT;
#endif