diff --git a/csu/init-first.c b/csu/init-first.c index 099e7bc..c7b8f1f 100644 --- a/csu/init-first.c +++ b/csu/init-first.c @@ -75,6 +75,10 @@ _init (int argc, char **argv, char **envp) /* First the initialization which normally would be done by the dynamic linker. */ _dl_non_dynamic_init (); + +# ifdef INIT_MBIND + INIT_MBIND (argv[0], _dl_phdr, _dl_phnum, 0); +# endif #endif #ifdef VDSO_SETUP diff --git a/elf/dl-init.c b/elf/dl-init.c index 5c5f3de..7bd6af6 100644 --- a/elf/dl-init.c +++ b/elf/dl-init.c @@ -35,6 +35,14 @@ call_init (struct link_map *l, int argc, char **argv, char **env) dependency. */ l->l_init_called = 1; +#ifdef INIT_MBIND + if (l->l_phdr) + { + const char *name = l->l_name[0] == '\0' ? argv[0] : l->l_name; + INIT_MBIND (name, l->l_phdr, l->l_phnum, l->l_addr); + } +#endif + /* Check for object which constructors we do not run here. */ if (__builtin_expect (l->l_name[0], 'a') == '\0' && l->l_type == lt_executable) diff --git a/elf/dl-support.c b/elf/dl-support.c index 3c46a7a..aa240c4 100644 --- a/elf/dl-support.c +++ b/elf/dl-support.c @@ -385,3 +385,7 @@ _dl_non_dynamic_init (void) #ifdef DL_SYSINFO_IMPLEMENTATION DL_SYSINFO_IMPLEMENTATION #endif + +#ifdef INIT_MBIND +# include +#endif diff --git a/elf/elf.h b/elf/elf.h index 6d3b356..a743cda 100644 --- a/elf/elf.h +++ b/elf/elf.h @@ -728,6 +728,11 @@ typedef struct #define PT_LOPROC 0x70000000 /* Start of processor-specific */ #define PT_HIPROC 0x7fffffff /* End of processor-specific */ +/* GNU mbind segments */ +#define PT_GNU_MBIND_NUM 4096 +#define PT_GNU_MBIND_LO 0x6474e555 +#define PT_GNU_MBIND_HI (PT_GNU_MBIND_LO + PT_GNU_MBIND_NUM - 1) + /* Legal values for p_flags (segment flags). */ #define PF_X (1 << 0) /* Segment is executable */ diff --git a/sysdeps/unix/sysv/linux/x86/ldsodefs.h b/sysdeps/unix/sysv/linux/x86/ldsodefs.h new file mode 100644 index 0000000..1b1c1f8 --- /dev/null +++ b/sysdeps/unix/sysv/linux/x86/ldsodefs.h @@ -0,0 +1,26 @@ +/* Run-time dynamic linker data structures for loaded ELF shared objects. x86 + Copyright (C) 2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _LDSODEFS_H + +/* Get the real definitions. */ +#include_next + +#include + +#endif /* ldsodefs.h */ diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile index 0d0326c2..7887a3c 100644 --- a/sysdeps/x86/Makefile +++ b/sysdeps/x86/Makefile @@ -3,7 +3,7 @@ gen-as-const-headers += cpu-features-offsets.sym endif ifeq ($(subdir),elf) -sysdep-dl-routines += dl-get-cpu-features +sysdep-dl-routines += dl-get-cpu-features setup-mbind tests += tst-get-cpu-features tests-static += tst-get-cpu-features-static diff --git a/sysdeps/x86/Versions b/sysdeps/x86/Versions index e029237..a627762 100644 --- a/sysdeps/x86/Versions +++ b/sysdeps/x86/Versions @@ -1,5 +1,8 @@ ld { GLIBC_PRIVATE { __get_cpu_features; + + # Set up special memory. + __gnu_mbind_setup; } } diff --git a/sysdeps/x86/init-mbind.h b/sysdeps/x86/init-mbind.h new file mode 100644 index 0000000..b881fdf --- /dev/null +++ b/sysdeps/x86/init-mbind.h @@ -0,0 +1,46 @@ +/* This file is part of the GNU C Library. + Copyright (C) 2016 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include + +static inline void +init_mbind (const char *filename, const ElfW(Phdr) *phdr, size_t phnum, + ElfW(Addr) load) +{ + ElfW(Addr) pagesize = GLRO(dl_pagesize); + for (; phnum; phnum--, phdr++) + if (phdr->p_type >= PT_GNU_MBIND_LO + && phdr->p_type <= PT_GNU_MBIND_HI) + { + ElfW(Addr) start = phdr->p_vaddr; + if (pagesize > phdr->p_align + || (start & (pagesize - 1)) != 0) + _dl_fatal_printf (N_("%s: invalid PT_GNU_MBIND segment\n"), + filename); + + int error_code = __gnu_mbind_setup (phdr->p_type - PT_GNU_MBIND_LO, + (void *) (load + start), + phdr->p_memsz); + if (error_code < 0) + _dl_fatal_printf (N_("__gnu_mbind_setup failed on file %s: error 0x%x\n"), + filename, -error_code); + } +} + +#define INIT_MBIND init_mbind diff --git a/sysdeps/x86/setup-mbind.c b/sysdeps/x86/setup-mbind.c new file mode 100644 index 0000000..d235b2e --- /dev/null +++ b/sysdeps/x86/setup-mbind.c @@ -0,0 +1,27 @@ +/* This file is part of the GNU C Library. + Copyright (C) 2016 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + + +#include + +int weak_function +__gnu_mbind_setup (unsigned int type __attribute__ ((unused)), + void *addr __attribute__ ((unused)), + size_t length __attribute__ ((unused))) +{ + return 0; +} diff --git a/sysdeps/x86/setup-mbind.h b/sysdeps/x86/setup-mbind.h new file mode 100644 index 0000000..f26972f --- /dev/null +++ b/sysdeps/x86/setup-mbind.h @@ -0,0 +1,21 @@ +/* This file is part of the GNU C Library. + Copyright (C) 2015 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + +/* Set up special memory. */ +extern int weak_function __gnu_mbind_setup (unsigned int, void *, size_t); diff --git a/sysdeps/x86_64/localplt.data b/sysdeps/x86_64/localplt.data index 014a9f4..8f4d47c 100644 --- a/sysdeps/x86_64/localplt.data +++ b/sysdeps/x86_64/localplt.data @@ -11,6 +11,7 @@ libc.so: realloc + RELA R_X86_64_GLOB_DAT libm.so: matherr # The main malloc is interposed into the dynamic linker, for # allocations after the initial link (when dlopen is used). +ld.so: __gnu_mbind_setup + RELA R_X86_64_GLOB_DAT ld.so: malloc + RELA R_X86_64_GLOB_DAT ld.so: calloc + RELA R_X86_64_GLOB_DAT ld.so: realloc + RELA R_X86_64_GLOB_DAT