ld.so: add an --argv0 option

Message ID 1461389300-29574-1-git-send-email-vapier@gentoo.org
State Changes Requested, archived
Delegated to: Mike Frysinger
Headers

Commit Message

Mike Frysinger April 23, 2016, 5:28 a.m. UTC
  Sometimes when you run a program you want the argv[0] string passed to
the app to be different than the actual path you used to load it.  We
can't do this today with invoking via ld.so which can be limiting --
some programs like to inspect their argv[0] and make decisions as to
how it should (re)exec itself or helper tools.  For example, clang and
gcc both do argv[0] inspection to support relocatable toolchains.
---
 elf/rtld.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)
  

Comments

Florian Weimer April 23, 2016, 12:21 p.m. UTC | #1
* Mike Frysinger:

> Sometimes when you run a program you want the argv[0] string passed to
> the app to be different than the actual path you used to load it.  We
> can't do this today with invoking via ld.so which can be limiting --
> some programs like to inspect their argv[0] and make decisions as to
> how it should (re)exec itself or helper tools.  For example, clang and
> gcc both do argv[0] inspection to support relocatable toolchains.

Interesting idea.  I think it's sufficiently to include this, but it
needs a ChangeLog entry and a test case.
  
Mike Frysinger April 23, 2016, 8:06 p.m. UTC | #2
On 23 Apr 2016 14:21, Florian Weimer wrote:
> * Mike Frysinger:
> > Sometimes when you run a program you want the argv[0] string passed to
> > the app to be different than the actual path you used to load it.  We
> > can't do this today with invoking via ld.so which can be limiting --
> > some programs like to inspect their argv[0] and make decisions as to
> > how it should (re)exec itself or helper tools.  For example, clang and
> > gcc both do argv[0] inspection to support relocatable toolchains.
> 
> Interesting idea.  I think it's sufficiently to include this, but it
> needs a ChangeLog entry and a test case.

for the test, seems like i'll have to write a small C file that just
displays its argv, and then another shell script which runs the ldso
against that simple program and checks the output.  unless anyone has
a simpler idea.
-mike
  
Florian Weimer April 24, 2016, 12:21 p.m. UTC | #3
* Mike Frysinger:

> On 23 Apr 2016 14:21, Florian Weimer wrote:
>> * Mike Frysinger:
>> > Sometimes when you run a program you want the argv[0] string passed to
>> > the app to be different than the actual path you used to load it.  We
>> > can't do this today with invoking via ld.so which can be limiting --
>> > some programs like to inspect their argv[0] and make decisions as to
>> > how it should (re)exec itself or helper tools.  For example, clang and
>> > gcc both do argv[0] inspection to support relocatable toolchains.
>> 
>> Interesting idea.  I think it's sufficiently to include this, but it
>> needs a ChangeLog entry and a test case.
>
> for the test, seems like i'll have to write a small C file that just
> displays its argv, and then another shell script which runs the ldso
> against that simple program and checks the output.  unless anyone has
> a simpler idea.

You'll need the shell script wrapper.

Supplying the expected value in another argument, with some prefix and
suffix character, and comparing argv[0] to the extracted orignal
argument, is likely simpler than writing argv[0] to standard output
and reading it back from the shell script.
  

Patch

diff --git a/elf/rtld.c b/elf/rtld.c
index 647661c..a42b5f6 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -796,6 +796,8 @@  dl_main (const ElfW(Phdr) *phdr,
 	 installing it.  */
       rtld_is_main = true;
 
+      char *argv0 = NULL;
+
       /* Note the place where the dynamic linker actually came from.  */
       GL(dl_rtld_map).l_name = rtld_progname;
 
@@ -850,6 +852,14 @@  dl_main (const ElfW(Phdr) *phdr,
 	    _dl_argc -= 2;
 	    _dl_argv += 2;
 	  }
+	else if (! strcmp (_dl_argv[1], "--argv0") && _dl_argc > 2)
+	  {
+	    argv0 = _dl_argv[2];
+
+	    _dl_skip_args += 2;
+	    _dl_argc -= 2;
+	    _dl_argv += 2;
+	  }
 	else
 	  break;
 
@@ -878,7 +888,8 @@  of this helper program; chances are you did not intend to run this program.\n\
 			variable LD_LIBRARY_PATH\n\
   --inhibit-rpath LIST  ignore RUNPATH and RPATH information in object names\n\
 			in LIST\n\
-  --audit LIST          use objects named in LIST as auditors\n");
+  --audit LIST          use objects named in LIST as auditors\n\
+  --argv0 STRING        set argv[0] to STRING before running\n");
 
       ++_dl_skip_args;
       --_dl_argc;
@@ -971,6 +982,10 @@  of this helper program; chances are you did not intend to run this program.\n\
 	    break;
 	  }
 #endif
+
+      /* Set the argv[0] string now that we've processed the executable.  */
+      if (argv0 != NULL)
+	_dl_argv[0] = argv0;
     }
   else
     {