git: 48cce2a2982f - main - tls: Introduce struct dtv and struct dtv_slot
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 07 May 2025 19:22:14 UTC
The branch main has been updated by jrtc27: URL: https://cgit.FreeBSD.org/src/commit/?id=48cce2a2982ff3d13327c6cfbdf9441539ce42b3 commit 48cce2a2982ff3d13327c6cfbdf9441539ce42b3 Author: Jessica Clarke <jrtc27@FreeBSD.org> AuthorDate: 2025-05-07 19:20:26 +0000 Commit: Jessica Clarke <jrtc27@FreeBSD.org> CommitDate: 2025-05-07 19:20:26 +0000 tls: Introduce struct dtv and struct dtv_slot Rather than treating the DTV as a raw array of uintptr_t, use proper struct types and gain the benefit of having different types for different members. In particular, the module slots now have real pointer types so less casting is generally needed. Note that, whilst struct dtv_slot may seem a little unnecessary, this will help downstream in CheriBSD where we wish to be able to easily alter the layout of a module's slot, which this helps abstract. Reviewed by: kib Differential Revision: https://reviews.freebsd.org/D50231 --- lib/libc/gen/tls.c | 34 ++++++----- libexec/rtld-elf/aarch64/reloc.c | 2 +- libexec/rtld-elf/amd64/reloc.c | 2 +- libexec/rtld-elf/arm/reloc.c | 2 +- libexec/rtld-elf/i386/reloc.c | 4 +- libexec/rtld-elf/powerpc/reloc.c | 2 +- libexec/rtld-elf/powerpc64/reloc.c | 2 +- libexec/rtld-elf/riscv/reloc.c | 2 +- libexec/rtld-elf/rtld.c | 118 ++++++++++++++++++++----------------- libexec/rtld-elf/rtld.h | 2 +- sys/sys/_tls_variant_i.h | 12 +++- sys/x86/include/tls.h | 12 +++- 12 files changed, 114 insertions(+), 80 deletions(-) diff --git a/lib/libc/gen/tls.c b/lib/libc/gen/tls.c index 5b6970ad3905..b26b13d45589 100644 --- a/lib/libc/gen/tls.c +++ b/lib/libc/gen/tls.c @@ -80,13 +80,13 @@ static void *libc_tls_init; void * __libc_tls_get_addr(void *vti) { - uintptr_t *dtv; + struct dtv *dtv; tls_index *ti; dtv = _tcb_get()->tcb_dtv; ti = vti; - return ((char *)dtv[ti->ti_module + 1] + (ti->ti_offset + - TLS_DTV_OFFSET)); + return (dtv->dtv_slots[ti->ti_module - 1].dtvs_tls + + (ti->ti_offset + TLS_DTV_OFFSET)); } #ifdef __i386__ @@ -200,7 +200,7 @@ get_tls_block_ptr(void *tcb, size_t tcbsize) void __libc_free_tls(void *tcb, size_t tcbsize, size_t tcbalign __unused) { - uintptr_t *dtv; + struct dtv *dtv; dtv = ((struct tcb *)tcb)->tcb_dtv; __je_bootstrap_free(dtv); @@ -230,7 +230,7 @@ __libc_free_tls(void *tcb, size_t tcbsize, size_t tcbalign __unused) void * __libc_allocate_tls(void *oldtcb, size_t tcbsize, size_t tcbalign) { - uintptr_t *dtv; + struct dtv *dtv; struct tcb *tcb; char *tls_block, *tls; size_t extra_size, maxalign, post_size, pre_size, tls_block_size; @@ -270,18 +270,19 @@ __libc_allocate_tls(void *oldtcb, size_t tcbsize, size_t tcbalign) /* Adjust the DTV. */ dtv = tcb->tcb_dtv; - dtv[2] = (uintptr_t)tls; + dtv->dtv_slots[0].dtvs_tls = tls; } else { - dtv = __je_bootstrap_malloc(3 * sizeof(uintptr_t)); + dtv = __je_bootstrap_malloc(sizeof(struct dtv) + + sizeof(struct dtv_slot)); if (dtv == NULL) { tls_msg("__libc_allocate_tls: Out of memory.\n"); abort(); } /* Build the DTV. */ tcb->tcb_dtv = dtv; - dtv[0] = 1; /* Generation. */ - dtv[1] = 1; /* Segments count. */ - dtv[2] = (uintptr_t)tls; + dtv->dtv_gen = 1; /* Generation. */ + dtv->dtv_size = 1; /* Segments count. */ + dtv->dtv_slots[0].dtvs_tls = tls; if (libc_tls_init_size > 0) memcpy(tls, libc_tls_init, libc_tls_init_size); @@ -301,7 +302,7 @@ void __libc_free_tls(void *tcb, size_t tcbsize __unused, size_t tcbalign) { size_t size; - uintptr_t *dtv; + struct dtv *dtv; uintptr_t tlsstart, tlsend; /* @@ -326,7 +327,7 @@ __libc_allocate_tls(void *oldtcb, size_t tcbsize, size_t tcbalign) { size_t size; char *tls_block, *tls; - uintptr_t *dtv; + struct dtv *dtv; struct tcb *tcb; tcbalign = MAX(tcbalign, libc_tls_init_align); @@ -340,7 +341,8 @@ __libc_allocate_tls(void *oldtcb, size_t tcbsize, size_t tcbalign) abort(); } memset(tls_block, 0, size + tcbsize); - dtv = __je_bootstrap_malloc(3 * sizeof(uintptr_t)); + dtv = __je_bootstrap_malloc(sizeof(struct dtv) + + sizeof(struct dtv_slot)); if (dtv == NULL) { tls_msg("__libc_allocate_tls: Out of memory.\n"); abort(); @@ -351,9 +353,9 @@ __libc_allocate_tls(void *oldtcb, size_t tcbsize, size_t tcbalign) tcb->tcb_self = tcb; tcb->tcb_dtv = dtv; - dtv[0] = 1; - dtv[1] = 1; - dtv[2] = (uintptr_t)tls; + dtv->dtv_gen = 1; + dtv->dtv_size = 1; + dtv->dtv_slots[0].dtvs_tls = tls; if (oldtcb != NULL) { /* diff --git a/libexec/rtld-elf/aarch64/reloc.c b/libexec/rtld-elf/aarch64/reloc.c index 3687c9385326..8182bb428bd2 100644 --- a/libexec/rtld-elf/aarch64/reloc.c +++ b/libexec/rtld-elf/aarch64/reloc.c @@ -629,7 +629,7 @@ allocate_initial_tls(Obj_Entry *objs) void * __tls_get_addr(tls_index* ti) { - uintptr_t **dtvp; + struct dtv **dtvp; dtvp = &_tcb_get()->tcb_dtv; return (tls_get_addr_common(dtvp, ti->ti_module, ti->ti_offset)); diff --git a/libexec/rtld-elf/amd64/reloc.c b/libexec/rtld-elf/amd64/reloc.c index b5750ac746b2..373a1cdd2d06 100644 --- a/libexec/rtld-elf/amd64/reloc.c +++ b/libexec/rtld-elf/amd64/reloc.c @@ -556,7 +556,7 @@ allocate_initial_tls(Obj_Entry *objs) void * __tls_get_addr(tls_index *ti) { - uintptr_t **dtvp; + struct dtv **dtvp; dtvp = &_tcb_get()->tcb_dtv; return (tls_get_addr_common(dtvp, ti->ti_module, ti->ti_offset)); diff --git a/libexec/rtld-elf/arm/reloc.c b/libexec/rtld-elf/arm/reloc.c index b10e6ce844d5..7bb7ce83e1bd 100644 --- a/libexec/rtld-elf/arm/reloc.c +++ b/libexec/rtld-elf/arm/reloc.c @@ -465,7 +465,7 @@ allocate_initial_tls(Obj_Entry *objs) void * __tls_get_addr(tls_index* ti) { - uintptr_t **dtvp; + struct dtv **dtvp; dtvp = &_tcb_get()->tcb_dtv; return (tls_get_addr_common(dtvp, ti->ti_module, ti->ti_offset)); diff --git a/libexec/rtld-elf/i386/reloc.c b/libexec/rtld-elf/i386/reloc.c index 3d724bcacb6f..ff4b1ebbb148 100644 --- a/libexec/rtld-elf/i386/reloc.c +++ b/libexec/rtld-elf/i386/reloc.c @@ -523,7 +523,7 @@ allocate_initial_tls(Obj_Entry *objs) __attribute__((__regparm__(1))) void * ___tls_get_addr(tls_index *ti) { - uintptr_t **dtvp; + struct dtv **dtvp; dtvp = &_tcb_get()->tcb_dtv; return (tls_get_addr_common(dtvp, ti->ti_module, ti->ti_offset)); @@ -533,7 +533,7 @@ ___tls_get_addr(tls_index *ti) void * __tls_get_addr(tls_index *ti) { - uintptr_t **dtvp; + struct dtv **dtvp; dtvp = &_tcb_get()->tcb_dtv; return (tls_get_addr_common(dtvp, ti->ti_module, ti->ti_offset)); diff --git a/libexec/rtld-elf/powerpc/reloc.c b/libexec/rtld-elf/powerpc/reloc.c index 4d5b1be6a429..283a02c53511 100644 --- a/libexec/rtld-elf/powerpc/reloc.c +++ b/libexec/rtld-elf/powerpc/reloc.c @@ -837,7 +837,7 @@ allocate_initial_tls(Obj_Entry *list) void* __tls_get_addr(tls_index* ti) { - uintptr_t **dtvp; + struct dtv **dtvp; dtvp = &_tcb_get()->tcb_dtv; return (tls_get_addr_common(dtvp, ti->ti_module, ti->ti_offset + diff --git a/libexec/rtld-elf/powerpc64/reloc.c b/libexec/rtld-elf/powerpc64/reloc.c index b0b5ca6419f7..b1ca871d2780 100644 --- a/libexec/rtld-elf/powerpc64/reloc.c +++ b/libexec/rtld-elf/powerpc64/reloc.c @@ -734,7 +734,7 @@ allocate_initial_tls(Obj_Entry *list) void* __tls_get_addr(tls_index* ti) { - uintptr_t **dtvp; + struct dtv **dtvp; dtvp = &_tcb_get()->tcb_dtv; return (tls_get_addr_common(dtvp, ti->ti_module, ti->ti_offset + diff --git a/libexec/rtld-elf/riscv/reloc.c b/libexec/rtld-elf/riscv/reloc.c index 80a0acd3510f..4b61c4b9a061 100644 --- a/libexec/rtld-elf/riscv/reloc.c +++ b/libexec/rtld-elf/riscv/reloc.c @@ -495,7 +495,7 @@ allocate_initial_tls(Obj_Entry *objs) void * __tls_get_addr(tls_index* ti) { - uintptr_t **dtvp; + struct dtv **dtvp; dtvp = &_tcb_get()->tcb_dtv; return (tls_get_addr_common(dtvp, ti->ti_module, ti->ti_offset + diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index cd564daa94a6..3a6863abfe0d 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -170,7 +170,7 @@ static int symlook_list(SymLook *, const Objlist *, DoneList *); static int symlook_needed(SymLook *, const Needed_Entry *, DoneList *); static int symlook_obj1_sysv(SymLook *, const Obj_Entry *); static int symlook_obj1_gnu(SymLook *, const Obj_Entry *); -static void *tls_get_addr_slow(uintptr_t **, int, size_t, bool) __noinline; +static void *tls_get_addr_slow(struct dtv **, int, size_t, bool) __noinline; static void trace_loaded_objects(Obj_Entry *, bool); static void unlink_object(Obj_Entry *); static void unload_object(Obj_Entry *, RtldLockState *lockstate); @@ -4312,7 +4312,7 @@ dlinfo(void *handle, int request, void *p) static void rtld_fill_dl_phdr_info(const Obj_Entry *obj, struct dl_phdr_info *phdr_info) { - uintptr_t **dtvp; + struct dtv **dtvp; phdr_info->dlpi_addr = (Elf_Addr)obj->relocbase; phdr_info->dlpi_name = obj->path; @@ -5350,24 +5350,26 @@ unref_dag(Obj_Entry *root) * Common code for MD __tls_get_addr(). */ static void * -tls_get_addr_slow(uintptr_t **dtvp, int index, size_t offset, bool locked) +tls_get_addr_slow(struct dtv **dtvp, int index, size_t offset, bool locked) { - uintptr_t *newdtv, *dtv; + struct dtv *newdtv, *dtv; RtldLockState lockstate; int to_copy; dtv = *dtvp; /* Check dtv generation in case new modules have arrived */ - if (dtv[0] != tls_dtv_generation) { + if (dtv->dtv_gen != tls_dtv_generation) { if (!locked) wlock_acquire(rtld_bind_lock, &lockstate); - newdtv = xcalloc(tls_max_index + 2, sizeof(uintptr_t)); - to_copy = dtv[1]; + newdtv = xcalloc(1, sizeof(struct dtv) + tls_max_index * + sizeof(struct dtv_slot)); + to_copy = dtv->dtv_size; if (to_copy > tls_max_index) to_copy = tls_max_index; - memcpy(&newdtv[2], &dtv[2], to_copy * sizeof(uintptr_t)); - newdtv[0] = tls_dtv_generation; - newdtv[1] = tls_max_index; + memcpy(newdtv->dtv_slots, dtv->dtv_slots, to_copy * + sizeof(struct dtv_slot)); + newdtv->dtv_gen = tls_dtv_generation; + newdtv->dtv_size = tls_max_index; free(dtv); if (!locked) lock_release(rtld_bind_lock, &lockstate); @@ -5375,27 +5377,29 @@ tls_get_addr_slow(uintptr_t **dtvp, int index, size_t offset, bool locked) } /* Dynamically allocate module TLS if necessary */ - if (dtv[index + 1] == 0) { + if (dtv->dtv_slots[index - 1].dtvs_tls == 0) { /* Signal safe, wlock will block out signals. */ if (!locked) wlock_acquire(rtld_bind_lock, &lockstate); - if (!dtv[index + 1]) - dtv[index + 1] = (uintptr_t)allocate_module_tls(index); + if (!dtv->dtv_slots[index - 1].dtvs_tls) + dtv->dtv_slots[index - 1].dtvs_tls = + allocate_module_tls(index); if (!locked) lock_release(rtld_bind_lock, &lockstate); } - return ((void *)(dtv[index + 1] + offset)); + return (dtv->dtv_slots[index - 1].dtvs_tls + offset); } void * -tls_get_addr_common(uintptr_t **dtvp, int index, size_t offset) +tls_get_addr_common(struct dtv **dtvp, int index, size_t offset) { - uintptr_t *dtv; + struct dtv *dtv; dtv = *dtvp; /* Check dtv generation in case new modules have arrived */ - if (__predict_true(dtv[0] == tls_dtv_generation && dtv[index + 1] != 0)) - return ((void *)(dtv[index + 1] + offset)); + if (__predict_true(dtv->dtv_gen == tls_dtv_generation && + dtv->dtv_slots[index - 1].dtvs_tls != 0)) + return (dtv->dtv_slots[index - 1].dtvs_tls + offset); return (tls_get_addr_slow(dtvp, index, offset, false)); } @@ -5436,7 +5440,7 @@ allocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcbsize, size_t tcbalign) { Obj_Entry *obj; char *tls_block; - uintptr_t *dtv; + struct dtv *dtv; struct tcb *tcb; char *addr; uintptr_t i; @@ -5469,18 +5473,22 @@ allocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcbsize, size_t tcbalign) /* Adjust the DTV. */ dtv = tcb->tcb_dtv; - for (i = 0; i < dtv[1]; i++) { - if (dtv[i + 2] >= (uintptr_t)oldtcb && - dtv[i + 2] < (uintptr_t)oldtcb + tls_static_space) { - dtv[i + 2] = (uintptr_t)((char *)tcb + - ((char *)dtv[i + 2] - (char *)oldtcb)); + for (i = 0; i < dtv->dtv_size; i++) { + if ((uintptr_t)dtv->dtv_slots[i].dtvs_tls >= + (uintptr_t)oldtcb && + (uintptr_t)dtv->dtv_slots[i].dtvs_tls < + (uintptr_t)oldtcb + tls_static_space) { + dtv->dtv_slots[i].dtvs_tls = (char *)tcb + + (dtv->dtv_slots[i].dtvs_tls - + (char *)oldtcb); } } } else { - dtv = xcalloc(tls_max_index + 2, sizeof(uintptr_t)); + dtv = xcalloc(1, sizeof(struct dtv) + tls_max_index * + sizeof(struct dtv_slot)); tcb->tcb_dtv = dtv; - dtv[0] = tls_dtv_generation; - dtv[1] = tls_max_index; + dtv->dtv_gen = tls_dtv_generation; + dtv->dtv_size = tls_max_index; for (obj = globallist_curr(objs); obj != NULL; obj = globallist_next(obj)) { @@ -5501,7 +5509,7 @@ allocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcbsize, size_t tcbalign) obj->tlssize - obj->tlsinitsize - tls_init_offset); } - dtv[obj->tlsindex + 1] = (uintptr_t)addr; + dtv->dtv_slots[obj->tlsindex - 1].dtvs_tls = addr; } } @@ -5511,10 +5519,10 @@ allocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcbsize, size_t tcbalign) void free_tls(void *tcb, size_t tcbsize, size_t tcbalign __unused) { - uintptr_t *dtv; + struct dtv *dtv; uintptr_t tlsstart, tlsend; size_t post_size; - size_t dtvsize, i, tls_init_align __unused; + size_t i, tls_init_align __unused; assert(tcbsize >= TLS_TCB_SIZE); tls_init_align = MAX(obj_main->tlsalign, 1); @@ -5526,11 +5534,11 @@ free_tls(void *tcb, size_t tcbsize, size_t tcbalign __unused) tlsend = (uintptr_t)tcb + tls_static_space; dtv = ((struct tcb *)tcb)->tcb_dtv; - dtvsize = dtv[1]; - for (i = 0; i < dtvsize; i++) { - if (dtv[i + 2] != 0 && (dtv[i + 2] < tlsstart || - dtv[i + 2] >= tlsend)) { - free((void *)dtv[i + 2]); + for (i = 0; i < dtv->dtv_size; i++) { + if (dtv->dtv_slots[i].dtvs_tls != NULL && + ((uintptr_t)dtv->dtv_slots[i].dtvs_tls < tlsstart || + (uintptr_t)dtv->dtv_slots[i].dtvs_tls >= tlsend)) { + free(dtv->dtv_slots[i].dtvs_tls); } } free(dtv); @@ -5550,7 +5558,7 @@ allocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcbsize, size_t tcbalign) Obj_Entry *obj; size_t size, ralign; char *tls_block; - uintptr_t *dtv, *olddtv; + struct dtv *dtv, *olddtv; struct tcb *tcb; char *addr; size_t i; @@ -5562,14 +5570,15 @@ allocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcbsize, size_t tcbalign) assert(tcbsize >= 2 * sizeof(uintptr_t)); tls_block = xmalloc_aligned(size, ralign, 0 /* XXX */); - dtv = xcalloc(tls_max_index + 2, sizeof(uintptr_t)); + dtv = xcalloc(1, sizeof(struct dtv) + tls_max_index * + sizeof(struct dtv_slot)); tcb = (struct tcb *)(tls_block + roundup(tls_static_space, ralign)); tcb->tcb_self = tcb; tcb->tcb_dtv = dtv; - dtv[0] = tls_dtv_generation; - dtv[1] = tls_max_index; + dtv->dtv_gen = tls_dtv_generation; + dtv->dtv_size = tls_max_index; if (oldtcb != NULL) { /* @@ -5584,11 +5593,14 @@ allocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcbsize, size_t tcbalign) * move them over. */ olddtv = ((struct tcb *)oldtcb)->tcb_dtv; - for (i = 0; i < olddtv[1]; i++) { - if (olddtv[i + 2] < (uintptr_t)oldtcb - size || - olddtv[i + 2] > (uintptr_t)oldtcb) { - dtv[i + 2] = olddtv[i + 2]; - olddtv[i + 2] = 0; + for (i = 0; i < olddtv->dtv_size; i++) { + if ((uintptr_t)olddtv->dtv_slots[i].dtvs_tls < + (uintptr_t)oldtcb - size || + (uintptr_t)olddtv->dtv_slots[i].dtvs_tls > + (uintptr_t)oldtcb) { + dtv->dtv_slots[i].dtvs_tls = + olddtv->dtv_slots[i].dtvs_tls; + olddtv->dtv_slots[i].dtvs_tls = NULL; } } @@ -5608,7 +5620,7 @@ allocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcbsize, size_t tcbalign) memcpy(addr, obj->tlsinit, obj->tlsinitsize); obj->static_tls_copied = true; } - dtv[obj->tlsindex + 1] = (uintptr_t)addr; + dtv->dtv_slots[obj->tlsindex - 1].dtvs_tls = addr; } } @@ -5618,9 +5630,9 @@ allocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcbsize, size_t tcbalign) void free_tls(void *tcb, size_t tcbsize __unused, size_t tcbalign) { - uintptr_t *dtv; + struct dtv *dtv; size_t size, ralign; - int dtvsize, i; + size_t i; uintptr_t tlsstart, tlsend; /* @@ -5633,18 +5645,18 @@ free_tls(void *tcb, size_t tcbsize __unused, size_t tcbalign) size = roundup(tls_static_space, ralign); dtv = ((struct tcb *)tcb)->tcb_dtv; - dtvsize = dtv[1]; tlsend = (uintptr_t)tcb; tlsstart = tlsend - size; - for (i = 0; i < dtvsize; i++) { - if (dtv[i + 2] != 0 && (dtv[i + 2] < tlsstart || - dtv[i + 2] > tlsend)) { - free((void *)dtv[i + 2]); + for (i = 0; i < dtv->dtv_size; i++) { + if (dtv->dtv_slots[i].dtvs_tls != NULL && + ((uintptr_t)dtv->dtv_slots[i].dtvs_tls < tlsstart || + (uintptr_t)dtv->dtv_slots[i].dtvs_tls > tlsend)) { + free(dtv->dtv_slots[i].dtvs_tls); } } free((void *)tlsstart); - free((void *)dtv); + free(dtv); } #endif /* TLS_VARIANT_II */ diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h index a15c1d6d159f..a92350b9387c 100644 --- a/libexec/rtld-elf/rtld.h +++ b/libexec/rtld-elf/rtld.h @@ -415,7 +415,7 @@ void _rtld_bind_start(void); void *rtld_resolve_ifunc(const Obj_Entry *obj, const Elf_Sym *def); void symlook_init(SymLook *, const char *); int symlook_obj(SymLook *, const Obj_Entry *); -void *tls_get_addr_common(uintptr_t **dtvp, int index, size_t offset); +void *tls_get_addr_common(struct dtv **dtvp, int index, size_t offset); void *allocate_tls(Obj_Entry *, void *, size_t, size_t); void free_tls(void *, size_t, size_t); void *allocate_module_tls(int index); diff --git a/sys/sys/_tls_variant_i.h b/sys/sys/_tls_variant_i.h index 0207585871b9..90defd41f309 100644 --- a/sys/sys/_tls_variant_i.h +++ b/sys/sys/_tls_variant_i.h @@ -37,8 +37,18 @@ struct pthread; +struct dtv_slot { + char *dtvs_tls; +}; + +struct dtv { + uintptr_t dtv_gen; + uintptr_t dtv_size; + struct dtv_slot dtv_slots[]; +}; + struct tcb { - uintptr_t *tcb_dtv; /* required by rtld */ + struct dtv *tcb_dtv; /* required by rtld */ struct pthread *tcb_thread; }; diff --git a/sys/x86/include/tls.h b/sys/x86/include/tls.h index 4b6b58b4a5e3..29d036fd4871 100644 --- a/sys/x86/include/tls.h +++ b/sys/x86/include/tls.h @@ -36,13 +36,23 @@ struct pthread; +struct dtv_slot { + char *dtvs_tls; +}; + +struct dtv { + uintptr_t dtv_gen; + uintptr_t dtv_size; + struct dtv_slot dtv_slots[]; +}; + /* * Variant II tcb, first two members are required by rtld, * %fs (amd64) / %gs (i386) points to the structure. */ struct tcb { struct tcb *tcb_self; /* required by rtld */ - uintptr_t *tcb_dtv; /* required by rtld */ + struct dtv *tcb_dtv; /* required by rtld */ struct pthread *tcb_thread; };