This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[patch] Adjust AT_EXECFN on explicit loader invocation
- From: Paul Pluzhnikov <ppluzhnikov at google dot com>
- To: libc-alpha at sourceware dot org
- Cc: ppluzhnikov at google dot com, asmindak at google dot com
- Date: Wed, 18 Sep 2013 15:21:47 -0700
- Subject: [patch] Adjust AT_EXECFN on explicit loader invocation
- Authentication-results: sourceware.org; auth=none
Greetings,
It is a common need for "sophisticated" binaries (such as Java) to be able
to find the main executable on disk (e.g. in order to symbolize a crash
stack trace).
One "signal" that could be used for this is AT_EXECFN, which Linux
kernel passes as part of the aux vector.
That works, but not when the executable is invoked via explicit ld-linux
invocation. E.g. running the test program below produces:
$ ./a.out
argv[0]: ./a.out
AT_EXECFN: ./a.out
$ /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 ./a.out
argv[0]: ./a.out
AT_EXECFN: /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
Attached patch fixes this.
Since the loader already adjusts AT_{PHDR,PHNUM,ENTRY} for the main
executable, it's only consistent to adjust AT_EXECFN as well.
Tested on Linux/x86_64.
Ok for trunk?
Thanks,
--
/// --- cut --- execfn.c ---
#include <elf.h>
#include <link.h>
#include <stdio.h>
int main(int argc, char *argv[], char *envp[])
{
char **e = envp;
ElfW (auxv_t) *aux;
printf("argv[0]: %s\n", argv[0]);
for (; *e != NULL; ++e)
;
for (aux = (ElfW (auxv_t) *) ++e; aux->a_type != AT_NULL; ++aux)
if (aux->a_type == AT_EXECFN)
{
printf("AT_EXECFN: %s\n", (char *) aux->a_un.a_val);
break;
}
return 0;
}
/// --- cut --- execfn.c ---
2013-09-19 Paul Pluzhnikov <ppluzhnikov@google.com>
* elf/rtld.c (dl_main): Adjust AT_EXECFN on explicit loader
invocation.
diff --git a/elf/rtld.c b/elf/rtld.c
index 91da88c..6fb93f8 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1118,6 +1118,9 @@ of this helper program; chances are you did not intend to run this program.\n\
case AT_ENTRY:
av->a_un.a_val = *user_entry;
break;
+ case AT_EXECFN:
+ av->a_un.a_val = (uintptr_t) _dl_argv[0];
+ break;
}
#endif
}