summaryrefslogtreecommitdiff
path: root/libexec/ld.so/loader.c
diff options
context:
space:
mode:
authorKurt Miller <kurt@cvs.openbsd.org>2021-03-16 18:03:07 +0000
committerKurt Miller <kurt@cvs.openbsd.org>2021-03-16 18:03:07 +0000
commitcac854ce9965eada1c4c7484797fb4a955c734a1 (patch)
treed1796249ba280b53316b63a81d410bf10715f11d /libexec/ld.so/loader.c
parent8680e3f8348aa00b73d29fcb938c05f8b761161d (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.c18
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);