diff options
author | Kurt Miller <kurt@cvs.openbsd.org> | 2021-03-16 18:03:07 +0000 |
---|---|---|
committer | Kurt Miller <kurt@cvs.openbsd.org> | 2021-03-16 18:03:07 +0000 |
commit | cac854ce9965eada1c4c7484797fb4a955c734a1 (patch) | |
tree | d1796249ba280b53316b63a81d410bf10715f11d /libexec/ld.so/loader.c | |
parent | 8680e3f8348aa00b73d29fcb938c05f8b761161d (diff) |
On i386 don't attempt to map shared libraries in low memory when
a large executable's .text section crosses the 512MB exec line.
Executables that have MAXTSIZ > 64MB can map above the default
512MB exec line. When this happens, shared libs that attempt to map
into low memory will find their .data section can not be mapped. ld.so
will attempt to remap the share lib at higher addresses until it can be
mapped. For very large executables like chrome this process is very
time consuming. This change detects how much of the executable's
.text section exceeds 512MB and uses that as the initial hint for
shared libs to map into which avoids attempting to map into blocked
memory.
okay deraadt@
Diffstat (limited to 'libexec/ld.so/loader.c')
-rw-r--r-- | libexec/ld.so/loader.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/libexec/ld.so/loader.c b/libexec/ld.so/loader.c index f63825ff231..18bd30af759 100644 --- a/libexec/ld.so/loader.c +++ b/libexec/ld.so/loader.c @@ -1,4 +1,4 @@ -/* $OpenBSD: loader.c,v 1.190 2019/12/17 03:16:07 guenther Exp $ */ +/* $OpenBSD: loader.c,v 1.191 2021/03/16 18:03:06 kurt Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -32,6 +32,7 @@ #include <sys/mman.h> #include <sys/exec.h> #include <sys/sysctl.h> +#include <machine/vmparam.h> #include <nlist.h> #include <string.h> #include <link.h> @@ -73,6 +74,7 @@ char *_dl_preload __boot_data = NULL; char *_dl_tracefmt1 __boot_data = NULL; char *_dl_tracefmt2 __boot_data = NULL; char *_dl_traceprog __boot_data = NULL; +void *_dl_exec_hint __boot_data = NULL; char **environ = NULL; char *__progname = NULL; @@ -461,7 +463,7 @@ _dl_boot(const char **argv, char **envp, const long dyn_loff, long *dl_data) unsigned int loop; int failed; struct dep_node *n; - Elf_Addr minva, maxva, exe_loff; + Elf_Addr minva, maxva, exe_loff, exec_end, cur_exec_end; Elf_Phdr *ptls = NULL; int align; @@ -499,7 +501,7 @@ _dl_boot(const char **argv, char **envp, const long dyn_loff, long *dl_data) _dl_loading_object = NULL; minva = ELF_NO_ADDR; - maxva = exe_loff = 0; + maxva = exe_loff = exec_end = 0; /* * Examine the user application and set up object information. @@ -539,6 +541,10 @@ _dl_boot(const char **argv, char **envp, const long dyn_loff, long *dl_data) next_load->start = (char *)TRUNC_PG(phdp->p_vaddr) + exe_loff; next_load->size = (phdp->p_vaddr & align) + phdp->p_filesz; next_load->prot = PFLAGS(phdp->p_flags); + cur_exec_end = (Elf_Addr)next_load->start + next_load->size; + if ((next_load->prot & PROT_EXEC) != 0 && + cur_exec_end > exec_end) + exec_end = cur_exec_end; break; case PT_TLS: if (phdp->p_filesz > phdp->p_memsz) @@ -557,6 +563,12 @@ _dl_boot(const char **argv, char **envp, const long dyn_loff, long *dl_data) exe_obj->load_size = maxva - minva; _dl_set_sod(exe_obj->load_name, &exe_obj->sod); +#ifdef __i386__ + if (exec_end > I386_MAX_EXE_ADDR) + _dl_exec_hint = (void *)ROUND_PG(exec_end-I386_MAX_EXE_ADDR); + DL_DEB(("_dl_exec_hint: 0x%lx\n", _dl_exec_hint)); +#endif + /* TLS bits in the base executable */ if (ptls != NULL && ptls->p_memsz) _dl_set_tls(exe_obj, ptls, exe_loff, NULL); |