When uclibc is built with static PIE support the _dl_load_base variable shared between the libc-tls.c and reloc_static_pie.c creates the dependency that requires linking reloc_static_pie.o into static position-dependent executables resulting in the following build errors: gcc -static test.c -o test ...ld: ...usr/lib/libc.a(reloc_static_pie.os):(.text+0x0): undefined reference to `_DYNAMIC'
Move _dl_load_base definition to libc-tls.c to resolve this dependency and fix static PDE build.
Signed-off-by: Max Filippov jcmvbkbc@gmail.com --- libc/misc/internals/reloc_static_pie.c | 2 +- libpthread/nptl/sysdeps/generic/libc-tls.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/libc/misc/internals/reloc_static_pie.c b/libc/misc/internals/reloc_static_pie.c index 578202d235a1..f66f7a4236c9 100644 --- a/libc/misc/internals/reloc_static_pie.c +++ b/libc/misc/internals/reloc_static_pie.c @@ -20,7 +20,7 @@ #include <elf.h> #include <dl-elf.h>
-ElfW(Addr) _dl_load_base = NULL; +extern ElfW(Addr) _dl_load_base;
void reloc_static_pie (ElfW(Addr) load_addr); diff --git a/libpthread/nptl/sysdeps/generic/libc-tls.c b/libpthread/nptl/sysdeps/generic/libc-tls.c index 0c8c558d05d3..e0e272e01dae 100644 --- a/libpthread/nptl/sysdeps/generic/libc-tls.c +++ b/libpthread/nptl/sysdeps/generic/libc-tls.c @@ -117,6 +117,7 @@ init_static_tls (size_t memsz, size_t align) GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx); }
+ElfW(Addr) _dl_load_base; void __libc_setup_tls (size_t tcbsize, size_t tcbalign); void __libc_setup_tls (size_t tcbsize, size_t tcbalign) @@ -143,8 +144,7 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign) #else initimage = (void *) phdr->p_vaddr; #if !defined(SHARED) && defined(STATIC_PIE) - extern ElfW(Addr) _dl_load_base; - initimage += _dl_load_base; + initimage += _dl_load_base; #endif #endif align = phdr->p_align;
I haven't had a chance to test this yet, but the original decision of placing it in reloc_static_pie.c was to ensure that when reloc_static_pie() accessed _dl_load_base it would do so without relying on relocations.
Do you mind letting me know which architecture you are building on? On one or two architectures I do make use of _DYNAMIC in _start() and I wonder if maybe that is leaking into static builds?
Also it doesn't look like you are 0 initializing _dl_load_base in its new location. This is a requirement since non-pie static binaries will hit the code path and expect _dl_load_base to be 0.
On Fri, Sep 2, 2022, 1:24 AM Max Filippov jcmvbkbc@gmail.com wrote:
When uclibc is built with static PIE support the _dl_load_base variable shared between the libc-tls.c and reloc_static_pie.c creates the dependency that requires linking reloc_static_pie.o into static position-dependent executables resulting in the following build errors: gcc -static test.c -o test ...ld: ...usr/lib/libc.a(reloc_static_pie.os):(.text+0x0): undefined reference to `_DYNAMIC'
Move _dl_load_base definition to libc-tls.c to resolve this dependency and fix static PDE build.
Signed-off-by: Max Filippov jcmvbkbc@gmail.com
libc/misc/internals/reloc_static_pie.c | 2 +- libpthread/nptl/sysdeps/generic/libc-tls.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/libc/misc/internals/reloc_static_pie.c b/libc/misc/internals/reloc_static_pie.c index 578202d235a1..f66f7a4236c9 100644 --- a/libc/misc/internals/reloc_static_pie.c +++ b/libc/misc/internals/reloc_static_pie.c @@ -20,7 +20,7 @@ #include <elf.h> #include <dl-elf.h>
-ElfW(Addr) _dl_load_base = NULL; +extern ElfW(Addr) _dl_load_base;
void reloc_static_pie (ElfW(Addr) load_addr); diff --git a/libpthread/nptl/sysdeps/generic/libc-tls.c b/libpthread/nptl/sysdeps/generic/libc-tls.c index 0c8c558d05d3..e0e272e01dae 100644 --- a/libpthread/nptl/sysdeps/generic/libc-tls.c +++ b/libpthread/nptl/sysdeps/generic/libc-tls.c @@ -117,6 +117,7 @@ init_static_tls (size_t memsz, size_t align) GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx); }
+ElfW(Addr) _dl_load_base; void __libc_setup_tls (size_t tcbsize, size_t tcbalign); void __libc_setup_tls (size_t tcbsize, size_t tcbalign) @@ -143,8 +144,7 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign) #else initimage = (void *) phdr->p_vaddr; #if !defined(SHARED) && defined(STATIC_PIE)
- extern ElfW(Addr) _dl_load_base;
- initimage += _dl_load_base;
initimage += _dl_load_base;
#endif #endif align = phdr->p_align; -- 2.30.2
devel mailing list -- devel@uclibc-ng.org To unsubscribe send an email to devel-leave@uclibc-ng.org
Hi linted,
thanks for your review.
On Thu, Sep 1, 2022 at 11:12 PM linted linted90@gmail.com wrote:
the original decision of placing it in reloc_static_pie.c was to ensure that when reloc_static_pie() accessed _dl_load_base it would do so without relying on relocations.
I don't see how placing the variable definition in the source code changes that: the linker will move it to the .bss section anyway and the function will have to have code to access it there. Also by the time _dl_load_base is used all relative relocations are done, so that shouldn't be the issue at all?
Do you mind letting me know which architecture you are building on?
I'm adding static pie support to a new architecture: xtensa. It has a couple of quirks here and there, so there will be more follow-up patches. I just thought that this issue is rather non-arch specific to deal with it separately.
On one or two architectures I do make use of _DYNAMIC in _start() and I wonder if maybe that is leaking into static builds?
I'm looking at the linker-generated map of the failing build and see the following lines in the list of archive members included to satisfy symbol reference:
.../usr/lib/libc.a(reloc_static_pie.os) .../usr/lib/libc.a(libc-tls.os) (_dl_load_base)
so clearly in my case it's the libc-tls.c reference to the _dl_load_base that pulls reloc_static_pie.o in. Even if it didn't produce the build error decoupling them is the right thing to do, because reloc_static_pie.o has nothing to do in the PDE.
Also it doesn't look like you are 0 initializing _dl_load_base in its new location.
I don't. With zero-initializer it goes into the .bss section, without it it goes to the common section. Either way it will be zero-initialized by the kernel ELF loader.