rtld: Implement LD_SHOW_AUXV

It dumps auxv as seen by interpreter, right before starting any user
code.

Copied from:	glibc
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
This commit is contained in:
Konstantin Belousov 2021-11-13 03:18:13 +02:00
parent 77c088ab21
commit 64ba1f4cf3
2 changed files with 73 additions and 1 deletions

View File

@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd August 15, 2021
.Dd November 13, 2021
.Dt RTLD 1
.Os
.Sh NAME
@ -309,6 +309,11 @@ will process the filtee dependencies of the loaded objects immediately,
instead of postponing it until required.
Normally, the filtees are opened at the time of the first symbol resolution
from the filter object.
.It Ev LD_SHOW_AUXV
If set, causes
.Nm
to dump content of the aux vector to standard output, before passing
control to any user code.
.El
.Sh DIRECT EXECUTION MODE
.Nm

View File

@ -104,6 +104,7 @@ static Obj_Entry *dlopen_object(const char *name, int fd, Obj_Entry *refobj,
static Obj_Entry *do_load_object(int, const char *, char *, struct stat *, int);
static int do_search_info(const Obj_Entry *obj, int, struct dl_serinfo *);
static bool donelist_check(DoneList *, const Obj_Entry *);
static void dump_auxv(Elf_Auxinfo **aux_info);
static void errmsg_restore(struct dlerror_save *);
static struct dlerror_save *errmsg_save(void);
static void *fill_search_info(const char *, size_t, void *);
@ -364,6 +365,7 @@ enum {
LD_TRACE_LOADED_OBJECTS_FMT1,
LD_TRACE_LOADED_OBJECTS_FMT2,
LD_TRACE_LOADED_OBJECTS_ALL,
LD_SHOW_AUXV,
};
struct ld_env_var_desc {
@ -396,6 +398,7 @@ static struct ld_env_var_desc ld_env_vars[] = {
LD_ENV_DESC(TRACE_LOADED_OBJECTS_FMT1, false),
LD_ENV_DESC(TRACE_LOADED_OBJECTS_FMT2, false),
LD_ENV_DESC(TRACE_LOADED_OBJECTS_ALL, false),
LD_ENV_DESC(SHOW_AUXV, false),
};
static const char *
@ -857,6 +860,9 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
if (rtld_verify_versions(&list_main) == -1 && !ld_tracing)
rtld_die();
if (ld_get_env_var(LD_SHOW_AUXV) != NULL)
dump_auxv(aux_info);
if (ld_tracing) { /* We're done */
trace_loaded_objects(obj_main);
exit(0);
@ -6058,6 +6064,67 @@ print_usage(const char *argv0)
" <args> Arguments to the executed process\n", argv0);
}
#define AUXFMT(at, xfmt) [at] = { .name = #at, .fmt = xfmt }
static const struct auxfmt {
const char *name;
const char *fmt;
} auxfmts[] = {
AUXFMT(AT_NULL, NULL),
AUXFMT(AT_IGNORE, NULL),
AUXFMT(AT_EXECFD, "%d"),
AUXFMT(AT_PHDR, "%p"),
AUXFMT(AT_PHENT, "%u"),
AUXFMT(AT_PHNUM, "%u"),
AUXFMT(AT_PAGESZ, "%u"),
AUXFMT(AT_BASE, "%#lx"),
AUXFMT(AT_FLAGS, "%#lx"),
AUXFMT(AT_ENTRY, "%p"),
AUXFMT(AT_NOTELF, NULL),
AUXFMT(AT_UID, "%d"),
AUXFMT(AT_EUID, "%d"),
AUXFMT(AT_GID, "%d"),
AUXFMT(AT_EGID, "%d"),
AUXFMT(AT_EXECPATH, "%s"),
AUXFMT(AT_CANARY, "%p"),
AUXFMT(AT_CANARYLEN, "%u"),
AUXFMT(AT_OSRELDATE, "%u"),
AUXFMT(AT_NCPUS, "%u"),
AUXFMT(AT_PAGESIZES, "%p"),
AUXFMT(AT_PAGESIZESLEN, "%u"),
AUXFMT(AT_TIMEKEEP, "%p"),
AUXFMT(AT_STACKPROT, "%#x"),
AUXFMT(AT_EHDRFLAGS, "%#lx"),
AUXFMT(AT_HWCAP, "%#lx"),
AUXFMT(AT_HWCAP2, "%#lx"),
AUXFMT(AT_BSDFLAGS, "%#lx"),
AUXFMT(AT_ARGC, "%u"),
AUXFMT(AT_ARGV, "%p"),
AUXFMT(AT_ENVC, "%p"),
AUXFMT(AT_ENVV, "%p"),
AUXFMT(AT_PS_STRINGS, "%p"),
AUXFMT(AT_FXRNG, "%p"),
};
static void
dump_auxv(Elf_Auxinfo **aux_info)
{
Elf_Auxinfo *auxp;
const struct auxfmt *fmt;
int i;
for (i = 0; i < AT_COUNT; i++) {
auxp = aux_info[i];
if (auxp == NULL)
continue;
fmt = &auxfmts[i];
if (fmt->fmt == NULL)
continue;
rtld_fdprintf(STDOUT_FILENO, "%s:\t", fmt->name);
rtld_fdprintfx(STDOUT_FILENO, fmt->fmt, auxp->a_un.a_ptr);
rtld_fdprintf(STDOUT_FILENO, "\n");
}
}
/*
* Overrides for libc_pic-provided functions.
*/