1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-29 11:41:21 +03:00

Linux: Consolidate auxiliary vector parsing

And optimize it slightly.

The large switch statement in _dl_sysdep_start can be replaced with
a large array.  This reduces source code and binary size.  On
i686-linux-gnu:

Before:

   text	   data	    bss	    dec	    hex	filename
   7791	     12	      0	   7803	   1e7b	elf/dl-sysdep.os

After:

   text	   data	    bss	    dec	    hex	filename
   7135	     12	      0	   7147	   1beb	elf/dl-sysdep.os

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
This commit is contained in:
Florian Weimer
2022-02-03 10:58:59 +01:00
parent f19fc997a5
commit 8c8510ab27
6 changed files with 107 additions and 181 deletions

View File

@ -21,13 +21,12 @@
#include <dl-auxv.h>
#include <dl-hwcap-check.h>
#include <dl-osinfo.h>
#include <dl-parse_auxv.h>
#include <dl-procinfo.h>
#include <dl-tunables.h>
#include <elf.h>
#include <entry.h>
#include <errno.h>
#include <fcntl.h>
#include <fpu_control.h>
#include <ldsodefs.h>
#include <libc-internal.h>
#include <libintl.h>
@ -63,24 +62,24 @@ void *_dl_random attribute_relro = NULL;
# define DL_STACK_END(cookie) ((void *) (cookie))
#endif
ElfW(Addr)
_dl_sysdep_start (void **start_argptr,
void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
ElfW(Addr) *user_entry, ElfW(auxv_t) *auxv))
/* Arguments passed to dl_main. */
struct dl_main_arguments
{
const ElfW(Phdr) *phdr = NULL;
ElfW(Word) phnum = 0;
const ElfW(Phdr) *phdr;
ElfW(Word) phnum;
ElfW(Addr) user_entry;
ElfW(auxv_t) *av;
#ifdef NEED_DL_SYSINFO
uintptr_t new_sysinfo = 0;
#endif
};
__libc_stack_end = DL_STACK_END (start_argptr);
/* Separate function, so that dl_main can be called without the large
array on the stack. */
static void
_dl_sysdep_parse_arguments (void **start_argptr,
struct dl_main_arguments *args)
{
_dl_argc = (intptr_t) *start_argptr;
_dl_argv = (char **) (start_argptr + 1); /* Necessary aliasing violation. */
_environ = _dl_argv + _dl_argc + 1;
for (char **tmp = _environ + 1; ; ++tmp)
for (char **tmp = _environ; ; ++tmp)
if (*tmp == NULL)
{
/* Another necessary aliasing violation. */
@ -88,75 +87,26 @@ _dl_sysdep_start (void **start_argptr,
break;
}
user_entry = (ElfW(Addr)) ENTRY_POINT;
GLRO(dl_platform) = NULL; /* Default to nothing known about the platform. */
dl_parse_auxv_t auxv_values = { 0, };
_dl_parse_auxv (GLRO(dl_auxv), auxv_values);
/* NB: Default to a constant CONSTANT_MINSIGSTKSZ. */
_Static_assert (__builtin_constant_p (CONSTANT_MINSIGSTKSZ),
"CONSTANT_MINSIGSTKSZ is constant");
GLRO(dl_minsigstacksize) = CONSTANT_MINSIGSTKSZ;
args->phdr = (const ElfW(Phdr) *) auxv_values[AT_PHDR];
args->phnum = auxv_values[AT_PHNUM];
args->user_entry = auxv_values[AT_ENTRY];
}
for (av = GLRO(dl_auxv); av->a_type != AT_NULL; av++)
switch (av->a_type)
{
case AT_PHDR:
phdr = (void *) av->a_un.a_val;
break;
case AT_PHNUM:
phnum = av->a_un.a_val;
break;
case AT_PAGESZ:
GLRO(dl_pagesize) = av->a_un.a_val;
break;
case AT_ENTRY:
user_entry = av->a_un.a_val;
break;
case AT_SECURE:
__libc_enable_secure = av->a_un.a_val;
break;
case AT_PLATFORM:
GLRO(dl_platform) = (void *) av->a_un.a_val;
break;
case AT_HWCAP:
GLRO(dl_hwcap) = (unsigned long int) av->a_un.a_val;
break;
case AT_HWCAP2:
GLRO(dl_hwcap2) = (unsigned long int) av->a_un.a_val;
break;
case AT_CLKTCK:
GLRO(dl_clktck) = av->a_un.a_val;
break;
case AT_FPUCW:
GLRO(dl_fpu_control) = av->a_un.a_val;
break;
#ifdef NEED_DL_SYSINFO
case AT_SYSINFO:
new_sysinfo = av->a_un.a_val;
break;
#endif
case AT_SYSINFO_EHDR:
GLRO(dl_sysinfo_dso) = (void *) av->a_un.a_val;
break;
case AT_RANDOM:
_dl_random = (void *) av->a_un.a_val;
break;
case AT_MINSIGSTKSZ:
GLRO(dl_minsigstacksize) = av->a_un.a_val;
break;
DL_PLATFORM_AUXV
}
ElfW(Addr)
_dl_sysdep_start (void **start_argptr,
void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
ElfW(Addr) *user_entry, ElfW(auxv_t) *auxv))
{
__libc_stack_end = DL_STACK_END (start_argptr);
struct dl_main_arguments dl_main_args;
_dl_sysdep_parse_arguments (start_argptr, &dl_main_args);
dl_hwcap_check ();
#ifdef NEED_DL_SYSINFO
if (new_sysinfo != 0)
{
/* Only set the sysinfo value if we also have the vsyscall DSO. */
if (GLRO(dl_sysinfo_dso) != 0)
GLRO(dl_sysinfo) = new_sysinfo;
}
#endif
__tunables_init (_environ);
/* Initialize DSO sorting algorithm after tunables. */
@ -187,8 +137,9 @@ _dl_sysdep_start (void **start_argptr,
if (__builtin_expect (__libc_enable_secure, 0))
__libc_check_standard_fds ();
(*dl_main) (phdr, phnum, &user_entry, GLRO(dl_auxv));
return user_entry;
(*dl_main) (dl_main_args.phdr, dl_main_args.phnum,
&dl_main_args.user_entry, GLRO(dl_auxv));
return dl_main_args.user_entry;
}
void