summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWaldemar Brodkorb <wbx@openadk.org>2024-03-17 18:01:24 +0100
committerWaldemar Brodkorb <wbx@openadk.org>2024-03-19 14:50:57 +0100
commitae11f049fc55c63a79b95ce0de69a1aee0d53faf (patch)
tree81cadde791e058896cb87e996c215dc469916b83
parent9e7b342fde5505c0a1d4968e9d70537ac406f640 (diff)
riscv64: sync with glibc, fix all TLS errors in uClibc-ng-test
-rw-r--r--ldso/ldso/riscv64/dl-sysdep.h21
-rw-r--r--ldso/ldso/riscv64/elfinterp.c4
-rw-r--r--libpthread/nptl/sysdeps/riscv64/dl-tls.h10
-rw-r--r--libpthread/nptl/sysdeps/riscv64/libc-tls.c2
-rw-r--r--libpthread/nptl/sysdeps/riscv64/tcb-offsets.sym7
-rw-r--r--libpthread/nptl/sysdeps/riscv64/tls.h117
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/riscv64/bits/pthreadtypes.h2
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/riscv64/createthread.c13
8 files changed, 77 insertions, 99 deletions
diff --git a/ldso/ldso/riscv64/dl-sysdep.h b/ldso/ldso/riscv64/dl-sysdep.h
index 91a45af46..01f3e49bf 100644
--- a/ldso/ldso/riscv64/dl-sysdep.h
+++ b/ldso/ldso/riscv64/dl-sysdep.h
@@ -58,23 +58,20 @@ unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
|| (__WORDSIZE == 64 && (type) == R_RISCV_TLS_TPREL64))) \
| (ELF_RTYPE_CLASS_COPY * ((type) == R_RISCV_COPY)))
-
-/* Return the link-time address of _DYNAMIC. */
+/* Return the run-time load address of the shared object. */
static inline ElfW(Addr)
-elf_machine_dynamic (void)
+elf_machine_load_address (void)
{
- extern ElfW(Addr) _GLOBAL_OFFSET_TABLE_ __attribute__ ((visibility ("hidden")));
- return _GLOBAL_OFFSET_TABLE_;
+ extern const ElfW(Ehdr) __ehdr_start attribute_hidden;
+ return (ElfW(Addr)) &__ehdr_start;
}
-
-/* Return the run-time load address of the shared object. */
-static __always_inline ElfW(Addr) __attribute__ ((unused))
-elf_machine_load_address (void)
+/* Return the link-time address of _DYNAMIC. */
+static inline ElfW(Addr)
+elf_machine_dynamic (void)
{
- ElfW(Addr) load_addr;
- __asm__ ("lla %0, _DYNAMIC" : "=r" (load_addr));
- return load_addr - elf_machine_dynamic ();
+ extern ElfW(Dyn) _DYNAMIC[] attribute_hidden;
+ return (ElfW(Addr)) _DYNAMIC - elf_machine_load_address ();
}
static __always_inline void
diff --git a/ldso/ldso/riscv64/elfinterp.c b/ldso/ldso/riscv64/elfinterp.c
index 427e7b8fd..5266d96b2 100644
--- a/ldso/ldso/riscv64/elfinterp.c
+++ b/ldso/ldso/riscv64/elfinterp.c
@@ -214,11 +214,11 @@ _dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
*reloc_addr = tls_tpnt->l_tls_modid;
break;
case R_RISCV_TLS_DTPREL64:
- *reloc_addr = symbol_addr + rpnt->r_addend;
+ *reloc_addr = symbol_addr - TLS_DTV_OFFSET + rpnt->r_addend;
break;
case R_RISCV_TLS_TPREL64:
CHECK_STATIC_TLS ((struct link_map *) tls_tpnt);
- *reloc_addr = tls_tpnt->l_tls_offset + symbol_addr + rpnt->r_addend - TLS_TCB_SIZE;
+ *reloc_addr = tls_tpnt->l_tls_offset + symbol_addr + rpnt->r_addend;
break;
#endif
default:
diff --git a/libpthread/nptl/sysdeps/riscv64/dl-tls.h b/libpthread/nptl/sysdeps/riscv64/dl-tls.h
index 01663edf3..31991be0d 100644
--- a/libpthread/nptl/sysdeps/riscv64/dl-tls.h
+++ b/libpthread/nptl/sysdeps/riscv64/dl-tls.h
@@ -21,4 +21,14 @@ typedef struct
unsigned long int ti_offset;
} tls_index;
+/* The thread pointer points to the first static TLS block. */
+#define TLS_TP_OFFSET 0
+
+/* Dynamic thread vector pointers point 0x800 past the start of each
+ TLS block. */
+#define TLS_DTV_OFFSET 0x800
+
extern void *__tls_get_addr (tls_index *ti);
+
+#define GET_ADDR_OFFSET (ti->ti_offset + TLS_DTV_OFFSET)
+#define __TLS_GET_ADDR(__ti) (__tls_get_addr (__ti) - TLS_DTV_OFFSET)
diff --git a/libpthread/nptl/sysdeps/riscv64/libc-tls.c b/libpthread/nptl/sysdeps/riscv64/libc-tls.c
index 67c3a6016..6c686aa8b 100644
--- a/libpthread/nptl/sysdeps/riscv64/libc-tls.c
+++ b/libpthread/nptl/sysdeps/riscv64/libc-tls.c
@@ -28,7 +28,7 @@ void *
__tls_get_addr (tls_index *ti)
{
dtv_t *dtv = THREAD_DTV ();
- return (char *) dtv[1].pointer.val + ti->ti_offset;
+ return (char *) dtv[1].pointer.val + GET_ADDR_OFFSET;
}
#endif
diff --git a/libpthread/nptl/sysdeps/riscv64/tcb-offsets.sym b/libpthread/nptl/sysdeps/riscv64/tcb-offsets.sym
index 86025a402..fe6856c5d 100644
--- a/libpthread/nptl/sysdeps/riscv64/tcb-offsets.sym
+++ b/libpthread/nptl/sysdeps/riscv64/tcb-offsets.sym
@@ -1,6 +1,7 @@
#include <sysdep.h>
#include <tls.h>
-MULTIPLE_THREADS_OFFSET offsetof (struct pthread, header.multiple_threads)
-TID_OFFSET offsetof (struct pthread, tid)
-TP_TO_PTHREAD_OFFSET -(sizeof (struct pthread) + sizeof (tcbhead_t))
+#define thread_offsetof(mem) (long)(offsetof (struct pthread, mem) - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)
+
+MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads)
+
diff --git a/libpthread/nptl/sysdeps/riscv64/tls.h b/libpthread/nptl/sysdeps/riscv64/tls.h
index f33e6ed77..d802ec2a9 100644
--- a/libpthread/nptl/sysdeps/riscv64/tls.h
+++ b/libpthread/nptl/sysdeps/riscv64/tls.h
@@ -1,6 +1,5 @@
/* Definition for thread-local data handling. NPTL/RISCV64 version.
Copyright (C) 2005, 2007, 2011 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
@@ -35,15 +34,6 @@ typedef union dtv
} pointer;
} dtv_t;
-typedef struct
-{
- dtv_t *dtv;
-} tcbhead_t;
-
-register tcbhead_t *__thread_self __asm__("tp");
-
-# define TLS_MULTIPLE_THREADS_IN_TCB 1
-
#else /* __ASSEMBLER__ */
# include <tcb-offsets.h>
#endif /* __ASSEMBLER__ */
@@ -58,71 +48,56 @@ register tcbhead_t *__thread_self __asm__("tp");
#ifndef __ASSEMBLER__
+register void *__thread_self __asm__("tp");
+# define READ_THREAD_POINTER() ({ __thread_self; })
+
/* Get system call information. */
# include <sysdep.h>
-/* The TP points to the start of the TLS block.
- * As I understand it, this isn't strictly that "TP points to DTV" - it's
- * more where to place the TCB in the TLS block. This will place it in
- * the beginning.
- *
- * Layout:
- * ------------------------------------
- * | PRE | TCB | TLS MEMORY .. |
- * ------------------------------------
- * ^ x4 / TP
- *
- * PRE is the struct pthread described below
- * TCB is tcbhead_t
- * TLS memory is where the TLS program sections are loaded
- *
- * See _dl_allocate_tls_storage and __libc_setup_tls for more information.
- */
+/* The TP points to the start of the TLS block. */
# define TLS_DTV_AT_TP 1
/* Get the thread descriptor definition. */
# include <../../descr.h>
-/* Requirements for the TCB. */
-# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
-# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
+typedef struct
+{
+ dtv_t *dtv;
+ void *private;
+} tcbhead_t;
-# define TLS_TCB_SIZE sizeof (tcbhead_t)
-# define TLS_TCB_ALIGN __alignof__ (tcbhead_t)
+/* This is the size of the initial TCB. Because our TCB is before the thread
+ pointer, we don't need this. */
+# define TLS_INIT_TCB_SIZE 0
+# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread)
-/* This is the size of the TCB. */
+/* This is the size of the TCB. Because our TCB is before the thread
+ pointer, we don't need this. */
+# define TLS_TCB_SIZE 0
+# define TLS_TCB_ALIGN __alignof__ (struct pthread)
-/* This is the size we need before TCB.
- * To support THREAD_GETMEM with friends we want to have a
- * struct pthread available.
- * Yank it in infront of everything, I'm sure nobody will mind.
- *
- * This memory is really allocated PRE the TLS block, so it's possible
- * to do ((char*)tlsblock) - TLS_PRE_TCB_SIZE to access it.
- * This is done for THREAD_SELF. */
-# define TLS_PRE_TCB_SIZE sizeof (struct pthread)
+/* This is the size we need before TCB - actually, it includes the TCB. */
+# define TLS_PRE_TCB_SIZE \
+ (sizeof (struct pthread) \
+ + ((sizeof (tcbhead_t) + __alignof (struct pthread) - 1) \
+ & ~(__alignof (struct pthread) - 1)))
+/* The thread pointer tp points to the end of the TCB.
+ The pthread_descr structure is immediately in front of the TCB. */
+# define TLS_TCB_OFFSET 0
-/* Install the dtv pointer.
- * When called, dtvp is a pointer not the DTV per say (which should start
- * with the generation counter) but to the length of the DTV.
- * We can always index with -1, so we store dtvp[1]
- */
+/* Install the dtv pointer. The pointer passed is to the element with
+ index -1 which contain the length. */
# define INSTALL_DTV(tcbp, dtvp) \
- (((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1)
+ (((tcbhead_t *) (tcbp))[-1].dtv = (dtvp) + 1)
-/* Install new dtv for current thread
- * In a logicial world dtv here would also point to the length of the DTV.
- * However it does not, this time it points to the generation counter,
- * so just store it.
- *
- * Note: -1 is still valid and contains the length. */
+/* Install new dtv for current thread */
# define INSTALL_NEW_DTV(dtv) \
(THREAD_DTV() = (dtv))
/* Return dtv of given thread descriptor. */
# define GET_DTV(tcbp) \
- (((tcbhead_t *) (tcbp))->dtv)
+ (((tcbhead_t *) (tcbp))[-1].dtv)
/* Code to initially initialize the thread pointer.
*
@@ -136,31 +111,21 @@ register tcbhead_t *__thread_self __asm__("tp");
* It's hard to fail this, so return NULL always.
*/
# define TLS_INIT_TP(tcbp, secondcall) \
- ({__thread_self = ((tcbhead_t *)tcbp + 1); NULL;})
+ ({ __thread_self = (char*)tcbp + TLS_TCB_OFFSET; NULL; })
-/* Return the address of the dtv for the current thread.
- *
- * Dereference TP, offset to dtv - really straightforward.
- * Remember that we made TP point to after tcb, so we need to reverse that.
- */
+/* Return the address of the dtv for the current thread. */
# define THREAD_DTV() \
- ((((tcbhead_t *)__thread_self)-1)->dtv)
+ (((tcbhead_t *) (READ_THREAD_POINTER () - TLS_TCB_OFFSET))[-1].dtv)
-/* Return the thread descriptor for the current thread.
- *
- * Return a pointer to the TLS_PRE area where we allocated space for
- * a struct pthread. Again, TP points to after tcbhead_t, compensate with
- * TLS_INIT_TCB_SIZE.
- *
- * I regard this is a seperate system from the "normal" TLS.
- */
+/* Return the thread descriptor for the current thread. */
# define THREAD_SELF \
- ((struct pthread *) ((char *) __thread_self - TLS_INIT_TCB_SIZE \
- - TLS_PRE_TCB_SIZE))
+ ((struct pthread *) (READ_THREAD_POINTER () \
+ - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE))
-/* Magic for libthread_db to know how to do THREAD_SELF. */
+/* Informs libthread_db that the thread pointer is register 4, which is used
+ * to know how to do THREAD_SELF. */
# define DB_THREAD_SELF \
- CONST_THREAD_AREA (64, sizeof (struct pthread))
+ REGISTER (64, 64, 4 * 8, - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)
/* Access to data in the thread descriptor is easy. */
#define THREAD_GETMEM(descr, member) \
@@ -172,6 +137,10 @@ register tcbhead_t *__thread_self __asm__("tp");
#define THREAD_SETMEM_NC(descr, member, idx, value) \
descr->member[idx] = (value)
+/* l_tls_offset == 0 is perfectly valid, so we have to use some different
+ value to mean unset l_tls_offset. */
+# define NO_TLS_OFFSET -1
+
/* Get and set the global scope generation counter in struct pthread. */
#define THREAD_GSCOPE_FLAG_UNUSED 0
#define THREAD_GSCOPE_FLAG_USED 1
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/riscv64/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/riscv64/bits/pthreadtypes.h
index 13d138cd3..e0c0534f6 100644
--- a/libpthread/nptl/sysdeps/unix/sysv/linux/riscv64/bits/pthreadtypes.h
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/riscv64/bits/pthreadtypes.h
@@ -101,7 +101,7 @@ typedef union
typedef union
{
char __size[__SIZEOF_PTHREAD_CONDATTR_T];
- long int __align;
+ int __align;
} pthread_condattr_t;
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/riscv64/createthread.c b/libpthread/nptl/sysdeps/unix/sysv/linux/riscv64/createthread.c
index 10bb1bbfe..3079007c7 100644
--- a/libpthread/nptl/sysdeps/unix/sysv/linux/riscv64/createthread.c
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/riscv64/createthread.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2012 Free Software Foundation, Inc.
+/* Copyright (C) 2005 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
@@ -7,16 +8,16 @@
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
+ 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; see the file COPYING.LIB. If
- not, see <http://www.gnu.org/licenses/>.  */
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
/* Value passed to 'clone' for initialization of the thread register. */
#define TLS_VALUE ((void *) (pd) \
- + TLS_PRE_TCB_SIZE + TLS_INIT_TCB_SIZE)
+ + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE)
-/* Get the real implementation. */
+/* Get the real implementation. */
#include <sysdeps/pthread/createthread.c>