Changeset 4f205248 in mainline


Ignore:
Timestamp:
2018-04-23T18:50:40Z (6 years ago)
Author:
Jiří Zárevúcky <jiri.zarevucky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
a2eb85d
Parents:
8d58fca
git-author:
Jiří Zárevúcky <jiri.zarevucky@…> (2018-04-23 17:47:09)
git-committer:
Jiří Zárevúcky <jiri.zarevucky@…> (2018-04-23 18:50:40)
Message:

Honor TLS alignment.

Location:
uspace/lib/c
Files:
16 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/arch/abs32le/src/tls.c

    r8d58fca r4f205248  
    3434#include <stdint.h>
    3535
    36 tcb_t *tls_alloc_arch(void **data, size_t size)
     36tcb_t *tls_alloc_arch(size_t size, size_t align)
    3737{
    38         return tls_alloc_variant_2(data, size);
     38        return tls_alloc_variant_2(size, align);
    3939}
    4040
    41 void tls_free_arch(tcb_t *tcb, size_t size)
     41void tls_free_arch(tcb_t *tcb, size_t size, size_t align)
    4242{
    43         tls_free_variant_2(tcb, size);
     43        tls_free_variant_2(tcb, size, align);
    4444}
    4545
  • uspace/lib/c/arch/amd64/src/tls.c

    r8d58fca r4f205248  
    3838#include <stddef.h>
    3939
    40 tcb_t *tls_alloc_arch(void **data, size_t size)
     40tcb_t *tls_alloc_arch(size_t size, size_t align)
    4141{
    42         return tls_alloc_variant_2(data, size);
     42        return tls_alloc_variant_2(size, align);
    4343}
    4444
    45 void tls_free_arch(tcb_t *tcb, size_t size)
     45void tls_free_arch(tcb_t *tcb, size_t size, size_t align)
    4646{
    47         tls_free_variant_2(tcb, size);
     47        tls_free_variant_2(tcb, size, align);
    4848}
    4949
  • uspace/lib/c/arch/arm32/src/tls.c

    r8d58fca r4f205248  
    3838#include <stddef.h>
    3939
    40 tcb_t *tls_alloc_arch(void **data, size_t size)
     40tcb_t *tls_alloc_arch(size_t size, size_t align)
    4141{
    42         return tls_alloc_variant_1(data, size);
     42        return tls_alloc_variant_1(size, align);
    4343}
    4444
    45 void tls_free_arch(tcb_t *tcb, size_t size)
     45void tls_free_arch(tcb_t *tcb, size_t size, size_t align)
    4646{
    47         tls_free_variant_1(tcb, size);
     47        tls_free_variant_1(tcb, size, align);
    4848}
    4949
  • uspace/lib/c/arch/ia32/src/rtld/reloc.c

    r8d58fca r4f205248  
    181181                case R_386_TLS_TPOFF:
    182182                        DPRINTF("fixup R_386_TLS_TPOFF\n");
    183                         *r_ptr = (dest->ioffs + sym_def->st_value) - dest->rtld->tls_size;
     183                        *r_ptr = sym_def->st_value + dest->tpoff;
    184184                        break;
    185185
  • uspace/lib/c/arch/ia32/src/tls.c

    r8d58fca r4f205248  
    4545#endif
    4646
    47 tcb_t *tls_alloc_arch(void **data, size_t size)
     47tcb_t *tls_alloc_arch(size_t size, size_t align)
    4848{
    49         return tls_alloc_variant_2(data, size);
     49        return tls_alloc_variant_2(size, align);
    5050}
    5151
    52 void tls_free_arch(tcb_t *tcb, size_t size)
     52void tls_free_arch(tcb_t *tcb, size_t size, size_t align)
    5353{
    54         tls_free_variant_2(tcb, size);
     54        tls_free_variant_2(tcb, size, align);
    5555}
    5656
  • uspace/lib/c/arch/ia64/src/tls.c

    r8d58fca r4f205248  
    3737#include <tls.h>
    3838
    39 tcb_t *tls_alloc_arch(void **data, size_t size)
     39tcb_t *tls_alloc_arch(size_t size, size_t align)
    4040{
    41         return tls_alloc_variant_1(data, size);
     41        return tls_alloc_variant_1(size, align);
    4242}
    4343
    44 void tls_free_arch(tcb_t *tcb, size_t size)
     44void tls_free_arch(tcb_t *tcb, size_t size, size_t align)
    4545{
    46         tls_free_variant_1(tcb, size);
     46        tls_free_variant_1(tcb, size, align);
    4747}
    4848
  • uspace/lib/c/arch/mips32/src/tls.c

    r8d58fca r4f205248  
    3737#include <stddef.h>
    3838
    39 tcb_t *tls_alloc_arch(void **data, size_t size)
     39tcb_t *tls_alloc_arch(size_t size, size_t align)
    4040{
    41         return tls_alloc_variant_1(data, size);
     41        return tls_alloc_variant_1(size, align);
    4242}
    4343
    44 void tls_free_arch(tcb_t *tcb, size_t size)
     44void tls_free_arch(tcb_t *tcb, size_t size, size_t align)
    4545{
    46         tls_free_variant_1(tcb, size);
     46        tls_free_variant_1(tcb, size, align);
    4747}
    4848
  • uspace/lib/c/arch/ppc32/src/tls.c

    r8d58fca r4f205248  
    3636#include <stddef.h>
    3737
    38 tcb_t *tls_alloc_arch(void **data, size_t size)
     38tcb_t *tls_alloc_arch(size_t size, size_t align)
    3939{
    40         return tls_alloc_variant_1(data, size);
     40        return tls_alloc_variant_1(size, align);
    4141}
    4242
    43 void tls_free_arch(tcb_t *tcb, size_t size)
     43void tls_free_arch(tcb_t *tcb, size_t size, size_t align)
    4444{
    45         tls_free_variant_1(tcb, size);
     45        tls_free_variant_1(tcb, size, align);
    4646}
    4747
  • uspace/lib/c/arch/riscv64/src/tls.c

    r8d58fca r4f205248  
    3333#include <stddef.h>
    3434
    35 tcb_t *tls_alloc_arch(void **data, size_t size)
     35tcb_t *tls_alloc_arch(size_t size, size_t align)
    3636{
    37         return tls_alloc_variant_2(data, size);
     37        return tls_alloc_variant_2(size, align);
    3838}
    3939
    40 void tls_free_arch(tcb_t *tcb, size_t size)
     40void tls_free_arch(tcb_t *tcb, size_t size, size_t align)
    4141{
    42         tls_free_variant_2(tcb, size);
     42        tls_free_variant_2(tcb, size, align);
    4343}
    4444
  • uspace/lib/c/arch/sparc64/src/tls.c

    r8d58fca r4f205248  
    3838#include <stddef.h>
    3939
    40 tcb_t *tls_alloc_arch(void **data, size_t size)
     40tcb_t *tls_alloc_arch(size_t size, size_t align)
    4141{
    42         return tls_alloc_variant_2(data, size);
     42        return tls_alloc_variant_2(size, align);
    4343}
    4444
    45 void tls_free_arch(tcb_t *tcb, size_t size)
     45void tls_free_arch(tcb_t *tcb, size_t size, size_t align)
    4646{
    47         tls_free_variant_2(tcb, size);
     47        tls_free_variant_2(tcb, size, align);
    4848}
    4949
  • uspace/lib/c/generic/rtld/module.c

    r8d58fca r4f205248  
    3535 */
    3636
     37#include <align.h>
    3738#include <adt/list.h>
    3839#include <elf/elf_load.h>
     
    4243#include <stdlib.h>
    4344#include <str.h>
     45#include <macros.h>
    4446
    4547#include <rtld/rtld.h>
     
    7274        const elf_segment_header_t *tls =
    7375            elf_get_phdr(__executable_start, PT_TLS);
    74         uintptr_t bias = elf_get_bias(__executable_start);
    75 
    76         module->tdata = (void *) (tls->p_vaddr + bias);
    77         module->tdata_size = tls->p_filesz;
    78         module->tbss_size = tls->p_memsz - tls->p_filesz;
    79         module->tls_align = tls->p_align;
     76
     77        if (tls) {
     78                uintptr_t bias = elf_get_bias(__executable_start);
     79                module->tdata = (void *) (tls->p_vaddr + bias);
     80                module->tdata_size = tls->p_filesz;
     81                module->tbss_size = tls->p_memsz - tls->p_filesz;
     82                module->tls_align = tls->p_align;
     83        } else {
     84                module->tdata = NULL;
     85                module->tdata_size = 0;
     86                module->tbss_size = 0;
     87                module->tls_align = 1;
     88        }
    8089
    8190        list_append(&module->modules_link, &rtld->modules);
     
    324333{
    325334#ifdef CONFIG_TLS_VARIANT_1
    326         list_foreach(rtld->modules, modules_link, module_t, m) {
    327                 m->ioffs = rtld->tls_size;
    328                 list_append(&m->imodules_link, &rtmd->imodules);
     335        rtld->tls_size = sizeof(tcb_t);
     336        rtld->tls_align = _Alignof(tcb_t);
     337
     338        list_foreach(rtld->modules, modules_link, module_t, m) {
     339                list_append(&m->imodules_link, &rtld->imodules);
     340                rtld->tls_align = max(rtld->tls_align, m->tls_align);
     341
     342                rtld->tls_size = ALIGN_UP(rtld->tls_size, m->tls_align);
     343                m->tpoff = rtld->tls_size;
    329344                rtld->tls_size += m->tdata_size + m->tbss_size;
    330345        }
    331 #else /* CONFIG_TLS_VARIANT_2 */
    332         size_t offs;
    333 
    334         list_foreach(rtld->modules, modules_link, module_t, m) {
     346
     347#else
     348        rtld->tls_size = 0;
     349        rtld->tls_align = _Alignof(tcb_t);
     350
     351        list_foreach(rtld->modules, modules_link, module_t, m) {
     352                list_append(&m->imodules_link, &rtld->imodules);
     353                rtld->tls_align = max(rtld->tls_align, m->tls_align);
     354
     355                /* We are allocating spans "backwards", here,
     356                 * as described in U. Drepper's paper.
     357                 */
    335358                rtld->tls_size += m->tdata_size + m->tbss_size;
    336         }
    337 
    338         offs = 0;
    339         list_foreach(rtld->modules, modules_link, module_t, m) {
    340                 offs += m->tdata_size + m->tbss_size;
    341                 m->ioffs = rtld->tls_size - offs;
    342                 list_append(&m->imodules_link, &rtld->imodules);
    343         }
     359                rtld->tls_size = ALIGN_UP(rtld->tls_size, m->tls_align);
     360                m->tpoff = -(ptrdiff_t) rtld->tls_size;
     361        }
     362
     363        /* We are in negative offsets. In order for the alignments to
     364         * be correct, "zero" offset (i.e. the total size) must be aligned
     365         * to the strictest alignment present.
     366         */
     367        rtld->tls_size = ALIGN_UP(rtld->tls_size, rtld->tls_align);
     368
     369        /* Space for the TCB. */
     370        rtld->tls_size += sizeof(tcb_t);
    344371#endif
    345372}
  • uspace/lib/c/generic/rtld/rtld.c

    r8d58fca r4f205248  
    152152tcb_t *rtld_tls_make(rtld_t *rtld)
    153153{
    154         void *data;
    155154        tcb_t *tcb;
    156         size_t offset;
    157155        void **dtv;
    158156        size_t nmods;
    159157        size_t i;
    160158
    161         tcb = tls_alloc_arch(&data, rtld->tls_size);
     159        tcb = tls_alloc_arch(rtld->tls_size, rtld->tls_align);
    162160        if (tcb == NULL)
    163161                return NULL;
     
    182180         */
    183181
    184 #ifdef CONFIG_TLS_VARIANT_1
    185         /*
    186          * Ascending addresses
    187          */
    188         offset = 0;
    189182        i = 1;
    190183        list_foreach(rtld->imodules, imodules_link, module_t, m) {
    191                 assert(i == m->id);
    192                 assert(offset + m->tdata_size + m->tbss_size <= rtld->tls_size);
    193                 dtv[i++] = data + offset;
    194                 memcpy(data + offset, m->tdata, m->tdata_size);
    195                 offset += m->tdata_size;
    196                 memset(data + offset, 0, m->tbss_size);
    197                 offset += m->tbss_size;
    198         }
    199 #else /* CONFIG_TLS_VARIANT_2 */
    200         /*
    201          * Descending addresses
    202          */
    203         offset = 0;
    204         i = 1;
    205         list_foreach(rtld->imodules, imodules_link, module_t, m) {
    206                 assert(i == m->id);
    207                 assert(offset + m->tdata_size + m->tbss_size <= rtld->tls_size);
    208                 offset += m->tbss_size;
    209                 memset(data + rtld->tls_size - offset, 0, m->tbss_size);
    210                 offset += m->tdata_size;
    211                 memcpy(data + rtld->tls_size - offset, m->tdata, m->tdata_size);
    212                 dtv[i++] = data + rtld->tls_size - offset;
    213         }
    214 #endif
     184                assert(i++ == m->id);
     185
     186                dtv[m->id] = (void *) tcb + m->tpoff;
     187
     188                assert(((uintptr_t) dtv[m->id]) % m->tls_align == 0);
     189
     190                memcpy(dtv[m->id], m->tdata, m->tdata_size);
     191                memset(dtv[m->id] + m->tdata_size, 0, m->tbss_size);
     192        }
    215193
    216194        tcb->dtv = dtv;
     
    259237                assert(!link_used(&m->imodules_link));
    260238
    261                 tls_block = malloc(m->tdata_size + m->tbss_size);
     239                tls_block = memalign(m->tls_align, m->tdata_size + m->tbss_size);
    262240                /* XXX This can fail if OOM */
    263241                assert(tls_block != NULL);
  • uspace/lib/c/generic/tls.c

    r8d58fca r4f205248  
    3636 */
    3737
     38#include <assert.h>
    3839#include <stddef.h>
    3940#include <align.h>
     
    4142#include <stdlib.h>
    4243#include <str.h>
     44#include <macros.h>
    4345#include <elf/elf.h>
    4446
     
    4749#endif
    4850
    49 size_t tls_get_size(void)
    50 {
    51 #ifdef CONFIG_RTLD
    52         if (runtime_env != NULL)
    53                 return runtime_env->tls_size;
     51#if !defined(CONFIG_TLS_VARIANT_1) && !defined(CONFIG_TLS_VARIANT_2)
     52#error Unknown TLS variant.
     53#endif
     54
     55/** Get address of static TLS block */
     56void *tls_get(void)
     57{
     58#ifdef CONFIG_RTLD
     59        assert(runtime_env == NULL);
    5460#endif
    5561
    5662        const elf_segment_header_t *tls =
    5763            elf_get_phdr(__executable_start, PT_TLS);
    58         return tls->p_memsz;
    59 }
    60 
    61 /** Get address of static TLS block */
    62 void *tls_get(void)
    63 {
     64
     65        if (tls == NULL)
     66                return NULL;
     67
    6468#ifdef CONFIG_TLS_VARIANT_1
    65         return (uint8_t *)__tcb_get() + sizeof(tcb_t);
     69        return (uint8_t *)__tcb_get() + ALIGN_UP(sizeof(tcb_t), tls->p_align);
    6670#else /* CONFIG_TLS_VARIANT_2 */
    67         return (uint8_t *)__tcb_get() - tls_get_size();
     71        return (uint8_t *)__tcb_get() - ALIGN_UP(tls->p_memsz, tls->p_align);
    6872#endif
    6973}
     
    8993
    9094        uintptr_t bias = elf_get_bias(__executable_start);
    91 
    92         tcb = tls_alloc_arch(&data, tls->p_memsz);
     95        size_t align = max(tls->p_align, _Alignof(tcb_t));
     96
     97#ifdef CONFIG_TLS_VARIANT_1
     98        tcb = tls_alloc_arch(
     99            ALIGN_UP(sizeof(tcb_t), align) + tls->p_memsz, align);
     100        data = (void *) tcb + ALIGN_UP(sizeof(tcb_t), align);
     101#else
     102        tcb = tls_alloc_arch(
     103            ALIGN_UP(tls->p_memsz, align) + sizeof(tcb_t), align);
     104        data = (void *) tcb - ALIGN_UP(tls->p_memsz, tls->p_align);
     105#endif
    93106
    94107        /*
     
    108121#ifdef CONFIG_RTLD
    109122        free(tcb->dtv);
    110 #endif
    111         tls_free_arch(tcb, tls_get_size());
     123
     124        if (runtime_env != NULL) {
     125                tls_free_arch(tcb, runtime_env->tls_size, runtime_env->tls_align);
     126                return;
     127        }
     128#endif
     129        const elf_segment_header_t *tls =
     130            elf_get_phdr(__executable_start, PT_TLS);
     131
     132        assert(tls != NULL);
     133        tls_free_arch(tcb,
     134            ALIGN_UP(tls->p_memsz, tls->p_align) + sizeof(tcb_t),
     135            max(tls->p_align, _Alignof(tcb_t)));
    112136}
    113137
     
    119143 * @return              Pointer to tcb_t structure.
    120144 */
    121 tcb_t *tls_alloc_variant_1(void **data, size_t size)
    122 {
    123         tcb_t *tcb;
    124 
    125         tcb = malloc(sizeof(tcb_t) + size);
     145tcb_t *tls_alloc_variant_1(size_t size, size_t align)
     146{
     147        tcb_t *tcb = memalign(align, size);
    126148        if (!tcb)
    127149                return NULL;
    128 
    129         *data = ((void *) tcb) + sizeof(tcb_t);
    130 #ifdef CONFIG_RTLD
    131         tcb->dtv = NULL;
    132 #endif
    133 
     150        memset(tcb, 0, sizeof(tcb_t));
    134151        return tcb;
    135152}
     
    140157 * @param size          This argument is ignored.
    141158 */
    142 void tls_free_variant_1(tcb_t *tcb, size_t size)
     159void tls_free_variant_1(tcb_t *tcb, size_t size, size_t align)
    143160{
    144161        free(tcb);
     
    152169 *                      actually an output argument.
    153170 * @param size          Size of thread local data.
     171 * @param align         Alignment of thread local data.
    154172 * @return              Pointer to TCB structure.
    155173 */
    156 tcb_t *tls_alloc_variant_2(void **data, size_t size)
    157 {
    158         tcb_t *tcb;
    159 
    160         uintptr_t align = elf_get_phdr(__executable_start, PT_TLS)->p_align;
    161 
    162         size = ALIGN_UP(size, align);
    163         *data = memalign(align, sizeof(tcb_t) + size);
    164         if (*data == NULL)
    165                 return NULL;
    166         tcb = (tcb_t *) (*data + size);
     174tcb_t *tls_alloc_variant_2(size_t size, size_t align)
     175{
     176        void *data = memalign(align, size);
     177        if (data == NULL)
     178                return NULL;
     179
     180        tcb_t *tcb = (tcb_t *) (data + size - sizeof(tcb_t));
     181        memset(tcb, 0, sizeof(tcb_t));
    167182        tcb->self = tcb;
    168 #ifdef CONFIG_RTLD
    169         tcb->dtv = NULL;
    170 #endif
    171 
    172183        return tcb;
    173184}
     
    177188 * @param tcb           Pointer to TCB structure.
    178189 * @param size          Size of thread local data.
    179  */
    180 void tls_free_variant_2(tcb_t *tcb, size_t size)
    181 {
    182         uintptr_t align = elf_get_phdr(__executable_start, PT_TLS)->p_align;
    183         size = ALIGN_UP(size, align);
    184         void *start = ((void *) tcb) - size;
    185         free(start);
     190 * @param align         Alignment of thread local data.
     191 */
     192void tls_free_variant_2(tcb_t *tcb, size_t size, size_t align)
     193{
     194        if (tcb != NULL) {
     195                void *start = ((void *) tcb) + sizeof(tcb_t) - size;
     196                free(start);
     197        }
    186198}
    187199#endif
  • uspace/lib/c/include/tls.h

    r8d58fca r4f205248  
    4444
    4545extern tcb_t *tls_make(void);
    46 extern tcb_t *tls_alloc_arch(void **, size_t);
     46extern tcb_t *tls_alloc_arch(size_t, size_t);
    4747extern void tls_free(tcb_t *);
    48 extern void tls_free_arch(tcb_t *, size_t);
    49 extern size_t tls_get_size(void);
     48extern void tls_free_arch(tcb_t *, size_t, size_t);
    5049extern void *tls_get(void);
    5150
    5251#ifdef CONFIG_TLS_VARIANT_1
    53 extern tcb_t *tls_alloc_variant_1(void **, size_t);
    54 extern void tls_free_variant_1(tcb_t *, size_t);
     52extern tcb_t *tls_alloc_variant_1(size_t, size_t);
     53extern void tls_free_variant_1(tcb_t *, size_t, size_t);
    5554#endif
    5655
    5756#ifdef CONFIG_TLS_VARIANT_2
    58 extern tcb_t *tls_alloc_variant_2(void **, size_t);
    59 extern void tls_free_variant_2(tcb_t *, size_t);
     57extern tcb_t *tls_alloc_variant_2(size_t, size_t);
     58extern void tls_free_variant_2(tcb_t *, size_t, size_t);
    6059#endif
    6160
  • uspace/lib/c/include/types/rtld/module.h

    r8d58fca r4f205248  
    6262        size_t tls_align;
    6363
    64         size_t ioffs;
     64        /** Offset of this module's TLS from the thread pointer. */
     65        ptrdiff_t tpoff;
    6566
    6667        /** Containing rtld */
  • uspace/lib/c/include/types/rtld/rtld.h

    r8d58fca r4f205248  
    5454        /** Size of initial TLS tdata + tbss */
    5555        size_t tls_size;
     56        size_t tls_align;
    5657
    5758        /** List of all loaded modules including rtld and the program */
Note: See TracChangeset for help on using the changeset viewer.