support setting of default thread stack size via PT_GNU_STACK header

this facilitates building software that assumes a large default stack
size without any patching to call pthread_setattr_default_np or
pthread_attr_setstacksize at each thread creation site, using just
LDFLAGS.

normally the PT_GNU_STACK header is used only to reflect whether
executable stack is desired, but with GNU ld at least, passing
-Wl,-z,stack-size=N will set a size on the program header. with this
patch, that size will be incorporated into the default stack size
(subject to increase-only rule and DEFAULT_STACK_MAX limit).

both static and dynamic linking honor the program header. for dynamic
linking, all libraries loaded at program start, including preloaded
ones, are considered. dlopened libraries are not considered, for
several reasons. extra logic would be needed to defer processing until
the load of the new library is commited, synchronization woud be
needed since other threads may be running concurrently, and the
effectiveness woud be limited since the larger size would not apply to
threads that already existed at the time of dlopen. programs that will
dlopen code expecting a large stack need to declare the requirement
themselves, or pthread_setattr_default_np can be used.
This commit is contained in:
Rich Felker 2018-09-18 23:54:18 -04:00
parent c0058ab465
commit 7b3348a98c
2 changed files with 17 additions and 0 deletions

View File

@ -609,6 +609,12 @@ static void *map_library(int fd, struct dso *dso)
} else if (ph->p_type == PT_GNU_RELRO) {
dso->relro_start = ph->p_vaddr & -PAGE_SIZE;
dso->relro_end = (ph->p_vaddr + ph->p_memsz) & -PAGE_SIZE;
} else if (ph->p_type == PT_GNU_STACK) {
if (!runtime && ph->p_memsz > __default_stacksize) {
__default_stacksize =
ph->p_memsz < DEFAULT_STACK_MAX ?
ph->p_memsz : DEFAULT_STACK_MAX;
}
}
if (ph->p_type != PT_LOAD) continue;
nsegs++;
@ -1238,6 +1244,12 @@ static void kernel_mapped_dso(struct dso *p)
} else if (ph->p_type == PT_GNU_RELRO) {
p->relro_start = ph->p_vaddr & -PAGE_SIZE;
p->relro_end = (ph->p_vaddr + ph->p_memsz) & -PAGE_SIZE;
} else if (ph->p_type == PT_GNU_STACK) {
if (!runtime && ph->p_memsz > __default_stacksize) {
__default_stacksize =
ph->p_memsz < DEFAULT_STACK_MAX ?
ph->p_memsz : DEFAULT_STACK_MAX;
}
}
if (ph->p_type != PT_LOAD) continue;
if (ph->p_vaddr < min_addr)

View File

@ -90,6 +90,11 @@ static void static_init_tls(size_t *aux)
base = (size_t)_DYNAMIC - phdr->p_vaddr;
if (phdr->p_type == PT_TLS)
tls_phdr = phdr;
if (phdr->p_type == PT_GNU_STACK &&
phdr->p_memsz > __default_stacksize)
__default_stacksize =
phdr->p_memsz < DEFAULT_STACK_MAX ?
phdr->p_memsz : DEFAULT_STACK_MAX;
}
if (tls_phdr) {