Changeset f356618 in mainline


Ignore:
Timestamp:
2016-05-22T21:05:55Z (9 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
b3364b7c
Parents:
af2254ec (diff), 3a9414e (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge dynamic linking support for thread local storage.

Files:
2 added
30 edited

Legend:

Unmodified
Added
Removed
  • .bzrignore

    raf2254ec rf356618  
    3535uspace/app/devctl/devctl
    3636uspace/app/dltest/dltest
     37uspace/app/dltests/dltests
    3738uspace/app/dnscfg/dnscfg
    3839uspace/app/dnsres/dnsres
     
    9697uspace/dist/app/devctl
    9798uspace/dist/app/dltest
     99uspace/dist/app/dltests
    98100uspace/dist/app/dnscfg
    99101uspace/dist/app/dnsres
  • abi/include/abi/elf.h

    raf2254ec rf356618  
    157157#define STT_SECTION  3
    158158#define STT_FILE     4
     159#define STT_TLS      6
    159160#define STT_LOPROC   13
    160161#define STT_HIPROC   15
     
    170171#define PT_SHLIB    5
    171172#define PT_PHDR     6
     173#define PT_TLS      7
    172174#define PT_LOPROC   0x70000000
    173175#define PT_HIPROC   0x7fffffff
  • boot/Makefile.common

    raf2254ec rf356618  
    226226ifeq ($(CONFIG_BUILD_SHARED_LIBS), y)
    227227        RD_APPS_NON_ESSENTIAL += \
    228                 $(USPACE_PATH)/app/dltest/dltest
     228                $(USPACE_PATH)/app/dltest/dltest \
     229                $(USPACE_PATH)/app/dltests/dltests
    229230endif
    230231
  • kernel/generic/src/lib/elf.c

    raf2254ec rf356618  
    163163        case PT_LOAD:
    164164                return load_segment(entry, elf, as);
     165        case PT_TLS:
     166                break;
    165167        case PT_DYNAMIC:
    166168        case PT_INTERP:
  • uspace/Makefile

    raf2254ec rf356618  
    4141        app/corecfg \
    4242        app/devctl \
    43         app/dltest \
    4443        app/dnscfg \
    4544        app/dnsres \
     
    167166        drv/platform/icp
    168167
     168
    169169## Platform-specific hardware support
    170170#
     
    210210                drv/fb/amdm37x_dispc \
    211211                srv/hw/irc/icp-ic
     212endif
     213
     214## Dynamic linking tests
     215#
     216ifeq ($(CONFIG_BUILD_SHARED_LIBS),y)
     217        DIRS += \
     218                app/dltest \
     219                app/dltests
    212220endif
    213221
  • uspace/Makefile.common

    raf2254ec rf356618  
    177177endif
    178178
    179 # Build static whenever we use libusb because that library uses
    180 # thread local variables
    181 ifneq ($(findstring usb, $(LIBS)),)
    182         STATIC_BUILD = y
    183 endif
    184 
    185 # Build static because libpcut is linked against libc which uses thread
    186 # local variables
    187 ifneq ($(TEST_SOURCES),)
    188         STATIC_BUILD = y
    189 endif
    190 
    191179ifeq ($(STATIC_BUILD),y)
    192180        BASE_LIBS = $(LIBC_PREFIX)/libc.a $(LIBSOFTINT_PREFIX)/libsoftint.a
    193         LINKER_SCRIPT ?= $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld
    194181        ifeq ($(MATH),y)
    195182                BASE_LIBS += $(LIBMATH_PREFIX)/libmath.a
     
    197184else
    198185        BASE_LIBS = $(LIBC_PREFIX)/libc.so.0 $(LIBSOFTINT_PREFIX)/libsoftint.so.0
    199         LFLAGS += -Bdynamic
    200         LINKER_SCRIPT ?= $(LIBC_PREFIX)/arch/$(UARCH)/_link-dlexe.ld
     186        LINK_DYNAMIC = y
    201187        ifeq ($(MATH),y)
    202188                BASE_LIBS += $(LIBMATH_PREFIX)/libmath.so.0
    203189        endif
     190endif
     191
     192ifeq ($(LINK_DYNAMIC),y)
     193        LFLAGS += -Bdynamic
     194        LINKER_SCRIPT ?= $(LIBC_PREFIX)/arch/$(UARCH)/_link-dlexe.ld
     195else
     196        LINKER_SCRIPT ?= $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld
    204197endif
    205198
  • uspace/app/dltest/Makefile

    raf2254ec rf356618  
    2828
    2929USPACE_PREFIX = ../..
    30 EXTRA_CFLAGS = -I$(LIBDLTEST_PREFIX)
     30EXTRA_CFLAGS = -I$(LIBDLTEST_PREFIX) -DDLTEST_LINKED
     31LIBS = $(LIBDLTEST_PREFIX)/libdltest.so.0.0
     32# Need a dynamic link, but possibly still use static libc
     33LINK_DYNAMIC = y
     34
    3135BINARY = dltest
    3236
  • uspace/app/dltest/dltest.c

    raf2254ec rf356618  
    4343
    4444/** libdltest library handle */
    45 void *handle;
     45static void *handle;
     46
     47/** If true, do not run dlfcn tests */
     48static bool no_dlfcn = false;
    4649
    4750/** Test dlsym() function */
     
    9396{
    9497        int (*p_dl_get_private_var)(void);
     98        int *(*p_dl_get_private_var_addr)(void);
    9599        int val;
    96100
     
    103107        }
    104108
     109        p_dl_get_private_var_addr = dlsym(handle, "dl_get_private_var_addr");
     110        if (p_dl_get_private_var_addr == NULL) {
     111                printf("FAILED\n");
     112                return false;
     113        }
     114
    105115        val = p_dl_get_private_var();
    106116
    107117        printf("Got %d, expected %d... ", val, dl_private_var_val);
    108118        if (val != dl_private_var_val) {
     119                printf("dl_get_private_var_addr -> %p\n",
     120                    p_dl_get_private_var_addr());
    109121                printf("FAILED\n");
    110122                return false;
     
    121133{
    122134        int (*p_dl_get_private_uvar)(void);
     135        int *(*p_dl_get_private_uvar_addr)(void);
    123136        int val;
    124137
     
    131144        }
    132145
     146        p_dl_get_private_uvar_addr = dlsym(handle, "dl_get_private_uvar_addr");
     147        if (p_dl_get_private_uvar_addr == NULL) {
     148                printf("FAILED\n");
     149                return false;
     150        }
     151
    133152        val = p_dl_get_private_uvar();
    134153
    135154        printf("Got %d, expected %d... ", val, 0);
    136155        if (val != 0) {
     156                printf("dl_get_private_uvar_addr -> %p\n",
     157                    p_dl_get_private_uvar_addr());
    137158                printf("FAILED\n");
    138159                return false;
     
    149170{
    150171        int (*p_dl_get_public_var)(void);
     172        int *(*p_dl_get_public_var_addr)(void);
    151173        int val;
    152174
     
    159181        }
    160182
     183        p_dl_get_public_var_addr = dlsym(handle, "dl_get_public_var_addr");
     184        if (p_dl_get_public_var_addr == NULL) {
     185                printf("FAILED\n");
     186                return false;
     187        }
     188
    161189        val = p_dl_get_public_var();
    162190
    163191        printf("Got %d, expected %d... ", val, dl_public_var_val);
    164192        if (val != dl_public_var_val) {
     193                printf("dl_get_public_var_addr -> %p\n",
     194                    p_dl_get_public_var_addr());
    165195                printf("FAILED\n");
    166196                return false;
     
    177207{
    178208        int (*p_dl_get_public_uvar)(void);
     209        int *(*p_dl_get_public_uvar_addr)(void);
    179210        int val;
    180211
     
    187218        }
    188219
     220        p_dl_get_public_uvar_addr = dlsym(handle, "dl_get_public_uvar_addr");
     221        if (p_dl_get_public_uvar_addr == NULL) {
     222                printf("FAILED\n");
     223                return false;
     224        }
     225
    189226        val = p_dl_get_public_uvar();
    190227
    191228        printf("Got %d, expected %d... ", val, 0);
    192229        if (val != 0) {
     230                printf("dl_get_public_uvar_addr -> %p\n",
     231                    p_dl_get_public_uvar_addr());
    193232                printf("FAILED\n");
    194233                return false;
     
    205244{
    206245        int *p_dl_public_var;
     246        int *(*p_dl_get_public_var_addr)(void);
    207247        int val;
    208248
     
    215255        }
    216256
     257        p_dl_get_public_var_addr = dlsym(handle, "dl_get_public_var_addr");
     258        if (p_dl_get_public_var_addr == NULL) {
     259                printf("FAILED\n");
     260                return false;
     261        }
     262
    217263        val = *p_dl_public_var;
    218264
    219265        printf("Got %d, expected %d... ", val, dl_public_var_val);
    220266        if (val != dl_public_var_val) {
     267                printf("&dl_public_var = %p, "
     268                    "dl_get_public_var_addr -> %p\n",
     269                    p_dl_public_var, p_dl_get_public_var_addr());
    221270                printf("FAILED\n");
    222271                return false;
     
    233282{
    234283        int *p_dl_public_uvar;
     284        int *(*p_dl_get_public_uvar_addr)(void);
    235285        int val;
    236286
     
    243293        }
    244294
     295        p_dl_get_public_uvar_addr = dlsym(handle, "dl_get_public_uvar_addr");
     296        if (p_dl_get_public_uvar_addr == NULL) {
     297                printf("FAILED\n");
     298                return false;
     299        }
     300
    245301        val = *p_dl_public_uvar;
    246302
    247303        printf("Got %d, expected %d... ", val, 0);
    248304        if (val != 0) {
    249                 printf("FAILED\n");
    250                 return false;
    251         }
    252 
    253         printf("Passed\n");
    254         return true;
    255 }
    256 
    257 int main(int argc, char *argv[])
    258 {
    259 
    260         printf("Dynamic linking test\n");
    261 
     305                printf("&dl_public_uvar = %p, "
     306                    "dl_get_public_uvar_addr -> %p\n",
     307                    p_dl_public_uvar, p_dl_get_public_uvar_addr());
     308                printf("FAILED\n");
     309                return false;
     310        }
     311
     312        printf("Passed\n");
     313        return true;
     314}
     315
     316#ifndef STATIC_EXE
     317
     318/** Test calling a function that returns contents of a private initialized
     319 * fibril-local variable.
     320 */
     321static bool test_dlfcn_dl_get_private_fib_var(void)
     322{
     323        int (*p_dl_get_private_fib_var)(void);
     324        int *(*p_dl_get_private_fib_var_addr)(void);
     325        int val;
     326
     327        printf("Call dlsym/dl_get_private_fib_var...\n");
     328
     329        p_dl_get_private_fib_var = dlsym(handle, "dl_get_private_fib_var");
     330        if (p_dl_get_private_fib_var == NULL) {
     331                printf("FAILED\n");
     332                return false;
     333        }
     334
     335        p_dl_get_private_fib_var_addr = dlsym(handle, "dl_get_private_fib_var_addr");
     336        if (p_dl_get_private_fib_var_addr == NULL) {
     337                printf("FAILED\n");
     338                return false;
     339        }
     340
     341        val = p_dl_get_private_fib_var();
     342
     343        printf("Got %d, expected %d... ", val, dl_private_fib_var_val);
     344        if (val != dl_private_fib_var_val) {
     345                printf("dl_get_private_fib_var_addr -> %p\n",
     346                    p_dl_get_private_fib_var_addr());
     347                printf("FAILED\n");
     348                return false;
     349        }
     350
     351        printf("Passed\n");
     352        return true;
     353}
     354
     355/** Test calling a function that returns contents of a private uninitialized
     356 * fibril-local variable.
     357 */
     358static bool test_dlfcn_dl_get_private_fib_uvar(void)
     359{
     360        int (*p_dl_get_private_fib_uvar)(void);
     361        int *(*p_dl_get_private_fib_uvar_addr)(void);
     362        int val;
     363
     364        printf("Call dlsym/dl_get_private_fib_uvar...\n");
     365
     366        p_dl_get_private_fib_uvar = dlsym(handle, "dl_get_private_fib_uvar");
     367        if (p_dl_get_private_fib_uvar == NULL) {
     368                printf("FAILED\n");
     369                return false;
     370        }
     371
     372        p_dl_get_private_fib_uvar_addr = dlsym(handle, "dl_get_private_fib_uvar_addr");
     373        if (p_dl_get_private_fib_uvar_addr == NULL) {
     374                printf("FAILED\n");
     375                return false;
     376        }
     377
     378        val = p_dl_get_private_fib_uvar();
     379
     380        printf("Got %d, expected %d... ", val, 0);
     381        if (val != 0) {
     382                printf("dl_get_private_fib_uvar_addr -> %p\n",
     383                    p_dl_get_private_fib_uvar_addr());
     384                printf("FAILED\n");
     385                return false;
     386        }
     387
     388        printf("Passed\n");
     389        return true;
     390}
     391
     392/** Test calling a function that returns the contents of a public initialized
     393 * fibril-local variable.
     394 */
     395static bool test_dlfcn_dl_get_public_fib_var(void)
     396{
     397        int (*p_dl_get_public_fib_var)(void);
     398        int *(*p_dl_get_public_fib_var_addr)(void);
     399        int val;
     400
     401        printf("Call dlsym/dl_get_public_fib_var...\n");
     402
     403        p_dl_get_public_fib_var = dlsym(handle, "dl_get_public_fib_var");
     404        if (p_dl_get_public_fib_var == NULL) {
     405                printf("FAILED\n");
     406                return false;
     407        }
     408
     409        p_dl_get_public_fib_var_addr = dlsym(handle, "dl_get_public_fib_var_addr");
     410        if (p_dl_get_public_fib_var_addr == NULL) {
     411                printf("FAILED\n");
     412                return false;
     413        }
     414
     415        val = p_dl_get_public_fib_var();
     416
     417        printf("Got %d, expected %d... ", val, dl_public_fib_var_val);
     418        if (val != dl_public_fib_var_val) {
     419                printf("dl_get_public_fib_var_addr -> %p\n",
     420                    p_dl_get_public_fib_var_addr());
     421                printf("FAILED\n");
     422                return false;
     423        }
     424
     425        printf("Passed\n");
     426        return true;
     427}
     428
     429/** Test calling a function that returns the contents of a public uninitialized
     430 * fibril-local variable.
     431 */
     432static bool test_dlfcn_dl_get_public_fib_uvar(void)
     433{
     434        int (*p_dl_get_public_fib_uvar)(void);
     435        int *(*p_dl_get_public_fib_uvar_addr)(void);
     436        int val;
     437
     438        printf("Call dlsym/dl_get_public_fib_uvar...\n");
     439
     440        p_dl_get_public_fib_uvar = dlsym(handle, "dl_get_public_fib_uvar");
     441        if (p_dl_get_public_fib_uvar == NULL) {
     442                printf("FAILED\n");
     443                return false;
     444        }
     445
     446        p_dl_get_public_fib_uvar_addr = dlsym(handle, "dl_get_public_fib_uvar_addr");
     447        if (p_dl_get_public_fib_uvar_addr == NULL) {
     448                printf("FAILED\n");
     449                return false;
     450        }
     451
     452        val = p_dl_get_public_fib_uvar();
     453
     454        printf("Got %d, expected %d... ", val, 0);
     455        if (val != 0) {
     456                printf("dl_get_public_fib_uvar_addr -> %p\n",
     457                    p_dl_get_public_fib_uvar_addr());
     458                printf("FAILED\n");
     459                return false;
     460        }
     461
     462        printf("Passed\n");
     463        return true;
     464}
     465
     466/** Test directly reading a public initialized fibril-local variable
     467 * whose address was obtained using dlsym.
     468 */
     469static bool test_dlfcn_read_public_fib_var(void)
     470{
     471        int *p_dl_public_fib_var;
     472        int *(*p_dl_get_public_fib_var_addr)(void);
     473        int val;
     474
     475        printf("Read dlsym/dl_public_fib_var...\n");
     476
     477        p_dl_public_fib_var = dlsym(handle, "dl_public_fib_var");
     478        if (p_dl_public_fib_var == NULL) {
     479                printf("FAILED\n");
     480                return false;
     481        }
     482
     483        p_dl_get_public_fib_var_addr = dlsym(handle, "dl_get_public_fib_var_addr");
     484        if (p_dl_get_public_fib_var_addr == NULL) {
     485                printf("FAILED\n");
     486                return false;
     487        }
     488
     489        val = *p_dl_public_fib_var;
     490
     491        printf("Got %d, expected %d... ", val, dl_public_fib_var_val);
     492        if (val != dl_public_fib_var_val) {
     493                printf("&dl_public_fib_var = %p, "
     494                    "dl_get_public_fib_var_addr -> %p\n",
     495                    p_dl_public_fib_var, p_dl_get_public_fib_var_addr());
     496                printf("FAILED\n");
     497                return false;
     498        }
     499
     500        printf("Passed\n");
     501        return true;
     502}
     503
     504/** Test directly reading a public uninitialized fibril-local variable
     505 * whose address was obtained using dlsym.
     506 */
     507static bool test_dlfcn_read_public_fib_uvar(void)
     508{
     509        int *p_dl_public_fib_uvar;
     510        int *(*p_dl_get_public_fib_uvar_addr)(void);
     511        int val;
     512
     513        printf("Read dlsym/dl_public_fib_uvar...\n");
     514
     515        p_dl_public_fib_uvar = dlsym(handle, "dl_public_fib_uvar");
     516        if (p_dl_public_fib_uvar == NULL) {
     517                printf("FAILED\n");
     518                return false;
     519        }
     520
     521        p_dl_get_public_fib_uvar_addr = dlsym(handle, "dl_get_public_fib_uvar_addr");
     522        if (p_dl_get_public_fib_uvar_addr == NULL) {
     523                printf("FAILED\n");
     524                return false;
     525        }
     526
     527        val = *p_dl_public_fib_uvar;
     528
     529        printf("Got %d, expected %d... ", val, 0);
     530        if (val != 0) {
     531                printf("&dl_public_fib_uvar = %p, "
     532                    "dl_get_public_fib_uvar_addr -> %p\n",
     533                    p_dl_public_fib_uvar, p_dl_get_public_fib_uvar_addr());
     534                printf("FAILED\n");
     535                return false;
     536        }
     537
     538        printf("Passed\n");
     539        return true;
     540}
     541
     542#endif /* STATIC_EXE */
     543
     544#ifdef DLTEST_LINKED
     545
     546/** Test directly calling function that returns a constant */
     547static bool test_lnk_dl_get_constant(void)
     548{
     549        int val;
     550
     551        printf("Call linked dl_get_constant...\n");
     552
     553        val = dl_get_constant();
     554
     555        printf("Got %d, expected %d... ", val, dl_constant);
     556        if (val != dl_constant) {
     557                printf("FAILED\n");
     558                return false;
     559        }
     560
     561        printf("Passed\n");
     562        return true;
     563}
     564
     565/** Test dircetly calling a function that returns contents of a private
     566 * initialized variable.
     567 */
     568static bool test_lnk_dl_get_private_var(void)
     569{
     570        int val;
     571
     572        printf("Call linked dl_get_private_var...\n");
     573
     574        val = dl_get_private_var();
     575
     576        printf("Got %d, expected %d... ", val, dl_private_var_val);
     577        if (val != dl_private_var_val) {
     578                printf("dl_get_private_var_addr -> %p\n",
     579                    dl_get_private_var_addr());
     580                printf("FAILED\n");
     581                return false;
     582        }
     583
     584        printf("Passed\n");
     585        return true;
     586}
     587
     588/** Test dircetly calling a function that returns contents of a private
     589 * uninitialized variable.
     590 */
     591static bool test_lnk_dl_get_private_uvar(void)
     592{
     593        int val;
     594
     595        printf("Call linked dl_get_private_uvar...\n");
     596
     597        val = dl_get_private_uvar();
     598
     599        printf("Got %d, expected %d... ", val, 0);
     600        if (val != 0) {
     601                printf("dl_get_private_uvar_addr -> %p\n",
     602                    dl_get_private_uvar_addr());
     603                printf("FAILED\n");
     604                return false;
     605        }
     606
     607        printf("Passed\n");
     608        return true;
     609}
     610
     611/** Test directly calling a function that returns the contents of a public
     612 * initialized variable.
     613 */
     614static bool test_lnk_dl_get_public_var(void)
     615{
     616        int val;
     617
     618        printf("Call linked dl_get_public_var...\n");
     619
     620        val = dl_get_public_var();
     621
     622        printf("Got %d, expected %d... ", val, dl_public_var_val);
     623        if (val != dl_public_var_val) {
     624                printf("dl_get_public_var_addr -> %p\n",
     625                    dl_get_public_var_addr());
     626                printf("FAILED\n");
     627                return false;
     628        }
     629
     630        printf("Passed\n");
     631        return true;
     632}
     633
     634/** Test directly calling a function that returns the contents of a public
     635 * uninitialized variable.
     636 */
     637static bool test_lnk_dl_get_public_uvar(void)
     638{
     639        int val;
     640
     641        printf("Call linked dl_get_public_uvar...\n");
     642
     643        val = dl_get_public_uvar();
     644
     645        printf("Got %d, expected %d... ", val, 0);
     646        if (val != 0) {
     647                printf("dl_get_public_uvar_addr -> %p\n",
     648                    dl_get_public_uvar_addr());
     649                printf("FAILED\n");
     650                return false;
     651        }
     652
     653        printf("Passed\n");
     654        return true;
     655}
     656
     657/** Test directly reading a public initialized variable. */
     658static bool test_lnk_read_public_var(void)
     659{
     660        int val;
     661
     662        printf("Read linked dl_public_var...\n");
     663
     664        val = dl_public_var;
     665
     666        printf("Got %d, expected %d... ", val, dl_public_var_val);
     667        if (val != dl_public_var_val) {
     668                printf("&dl_public_var = %p, dl_get_public_var_addr -> %p\n",
     669                    &dl_public_var, dl_get_public_var_addr());
     670                printf("FAILED\n");
     671                return false;
     672        }
     673
     674        printf("Passed\n");
     675        return true;
     676}
     677
     678/** Test directly reading a public uninitialized variable. */
     679static bool test_lnk_read_public_uvar(void)
     680{
     681        int val;
     682
     683        printf("Read linked dl_public_uvar...\n");
     684
     685        val = dl_public_uvar;
     686
     687        printf("Got %d, expected %d... ", val, 0);
     688        if (val != 0) {
     689                printf("&dl_public_uvar = %p, dl_get_public_uvar_addr -> %p\n",
     690                    &dl_public_uvar, dl_get_public_uvar_addr());
     691                printf("FAILED\n");
     692                return false;
     693        }
     694
     695        printf("Passed\n");
     696        return true;
     697}
     698
     699/** Test dircetly calling a function that returns contents of a private
     700 * initialized fibril-local variable.
     701 */
     702static bool test_lnk_dl_get_private_fib_var(void)
     703{
     704        int val;
     705
     706        printf("Call linked dl_get_private_fib_var...\n");
     707
     708        val = dl_get_private_fib_var();
     709
     710        printf("Got %d, expected %d... ", val, dl_private_fib_var_val);
     711        if (val != dl_private_fib_var_val) {
     712                printf("dl_get_private_fib_var_addr -> %p\n",
     713                    dl_get_private_fib_var_addr());
     714                printf("FAILED\n");
     715                return false;
     716        }
     717
     718        printf("Passed\n");
     719        return true;
     720}
     721
     722/** Test dircetly calling a function that returns contents of a private
     723 * uninitialized fibril-local variable.
     724 */
     725static bool test_lnk_dl_get_private_fib_uvar(void)
     726{
     727        int val;
     728
     729        printf("Call linked dl_get_private_fib_uvar...\n");
     730
     731        val = dl_get_private_fib_uvar();
     732
     733        printf("Got %d, expected %d... ", val, 0);
     734        if (val != 0) {
     735                printf("dl_get_private_fib_uvar_addr -> %p\n",
     736                    dl_get_private_fib_var_addr());
     737                printf("FAILED\n");
     738                return false;
     739        }
     740
     741        printf("Passed\n");
     742        return true;
     743}
     744
     745/** Test directly calling a function that returns the contents of a public
     746 * initialized fibril-local variable.
     747 */
     748static bool test_lnk_dl_get_public_fib_var(void)
     749{
     750        int val;
     751
     752        printf("Call linked dl_get_public_fib_var...\n");
     753
     754        val = dl_get_public_fib_var();
     755
     756        printf("Got %d, expected %d... ", val, dl_public_fib_var_val);
     757        if (val != dl_public_fib_var_val) {
     758                printf("dl_get_public_fib_var_addr -> %p\n",
     759                    dl_get_public_fib_var_addr());
     760                printf("FAILED\n");
     761                return false;
     762        }
     763
     764        printf("Passed\n");
     765        return true;
     766}
     767
     768/** Test directly calling a function that returns the contents of a public
     769 * uninitialized fibril-local variable.
     770 */
     771static bool test_lnk_dl_get_public_fib_uvar(void)
     772{
     773        int val;
     774
     775        printf("Call linked dl_get_public_fib_uvar...\n");
     776
     777        val = dl_get_public_fib_uvar();
     778
     779        printf("Got %d, expected %d... ", val, 0);
     780        if (val != 0) {
     781                printf("dl_get_public_fib_uvar_addr -> %p\n",
     782                    dl_get_public_fib_uvar_addr());
     783                printf("FAILED\n");
     784                return false;
     785        }
     786
     787        printf("Passed\n");
     788        return true;
     789}
     790
     791/** Test directly reading a public initialized fibril-local variable. */
     792static bool test_lnk_read_public_fib_var(void)
     793{
     794        int val;
     795
     796        printf("Read linked dl_public_fib_var...\n");
     797
     798        val = dl_public_fib_var;
     799
     800        printf("Got %d, expected %d... ", val, dl_public_fib_var_val);
     801        if (val != dl_public_fib_var_val) {
     802                printf("&dl_public_fib_var = %p, "
     803                    "dl_get_public_fib_var_addr -> %p\n",
     804                    &dl_public_fib_var, dl_get_public_fib_var_addr());
     805                printf("FAILED\n");
     806                return false;
     807        }
     808
     809        printf("Passed\n");
     810        return true;
     811}
     812
     813/** Test directly reading a public uninitialized fibril-local variable. */
     814static bool test_lnk_read_public_fib_uvar(void)
     815{
     816        int val;
     817
     818        printf("Read linked dl_public_fib_uvar...\n");
     819
     820        val = dl_public_fib_uvar;
     821
     822        printf("Got %d, expected %d... ", val, 0);
     823        if (val != 0) {
     824                printf("&dl_public_fib_uvar = %p, "
     825                    "dl_get_public_fib_uvar_addr -> %p\n",
     826                    &dl_public_fib_uvar, dl_get_public_fib_uvar_addr());
     827                printf("FAILED\n");
     828                return false;
     829        }
     830
     831        printf("Passed\n");
     832        return true;
     833}
     834
     835#endif /* DLTEST_LINKED */
     836
     837static int test_dlfcn(void)
     838{
    262839        printf("dlopen()... ");
    263840        handle = dlopen("libdltest.so.0", 0);
     
    293870                return 1;
    294871
     872#ifndef STATIC_EXE
     873        if (!test_dlfcn_dl_get_private_fib_var())
     874                return 1;
     875
     876        if (!test_dlfcn_dl_get_private_fib_uvar())
     877                return 1;
     878
     879        if (!test_dlfcn_dl_get_public_fib_var())
     880                return 1;
     881
     882        if (!test_dlfcn_dl_get_public_fib_uvar())
     883                return 1;
     884
     885        if (!test_dlfcn_read_public_fib_var())
     886                return 1;
     887
     888        if (!test_dlfcn_read_public_fib_uvar())
     889                return 1;
     890#endif /* STATIC_EXE */
     891
    295892//      printf("dlclose()... ");
    296893//      dlclose(handle);
    297894//      printf("Passed\n");
    298895
     896        return 0;
     897}
     898
     899#ifdef DLTEST_LINKED
     900
     901static int test_lnk(void)
     902{
     903        if (!test_lnk_dl_get_constant())
     904                return 1;
     905
     906        if (!test_lnk_dl_get_private_var())
     907                return 1;
     908
     909        if (!test_lnk_dl_get_private_uvar())
     910                return 1;
     911
     912        if (!test_lnk_dl_get_public_var())
     913                return 1;
     914
     915        if (!test_lnk_dl_get_public_uvar())
     916                return 1;
     917
     918        if (!test_lnk_read_public_var())
     919                return 1;
     920
     921        if (!test_lnk_read_public_uvar())
     922                return 1;
     923
     924        if (!test_lnk_dl_get_private_fib_var())
     925                return 1;
     926
     927        if (!test_lnk_dl_get_private_fib_uvar())
     928                return 1;
     929
     930        if (!test_lnk_dl_get_public_fib_var())
     931                return 1;
     932
     933        if (!test_lnk_dl_get_public_fib_uvar())
     934                return 1;
     935
     936        if (!test_lnk_read_public_fib_var())
     937                return 1;
     938
     939        if (!test_lnk_read_public_fib_uvar())
     940                return 1;
     941
     942        return 0;
     943}
     944
     945#endif /* DLTEST_LINKED */
     946
     947static void print_syntax(void)
     948{
     949        fprintf(stderr, "syntax: dltest [-n]\n");
     950        fprintf(stderr, "\t-n Do not run dlfcn tests\n");
     951}
     952
     953int main(int argc, char *argv[])
     954{
     955        printf("Dynamic linking test\n");
     956
     957        if (argc > 1) {
     958                if (argc > 2) {
     959                        print_syntax();
     960                        return 1;
     961                }
     962
     963                if (str_cmp(argv[1], "-n") == 0) {
     964                        no_dlfcn = true;
     965                } else {
     966                        print_syntax();
     967                        return 1;
     968                }
     969        }
     970
     971        if (!no_dlfcn) {
     972                if (test_dlfcn() != 0)
     973                        return 1;
     974        }
     975
     976#ifdef DLTEST_LINKED
     977        if (test_lnk() != 0)
     978                return 1;
     979#endif
     980
    299981        printf("All passed.\n");
    300982        return 0;
  • uspace/lib/c/arch/ia32/_link.ld.in

    raf2254ec rf356618  
    1212#endif
    1313        data PT_LOAD FLAGS(6);
     14        tls PT_TLS;
    1415#if defined(SHLIB) || defined(DLEXE)
    1516        dynamic PT_DYNAMIC;
     
    9596#endif
    9697       
     98        .tdata : {
    9799#ifndef DLEXE
    98         .tdata : {
    99100                _tdata_start = .;
     101#endif
    100102                *(.tdata);
    101103                *(.gnu.linkonce.tb.*);
     104#ifndef DLEXE
    102105                _tdata_end = .;
     106#endif
     107        } :data :tls
     108        .tbss : {
     109#ifndef DLEXE
    103110                _tbss_start = .;
     111#endif
    104112                *(.tbss);
     113#ifndef DLEXE
    105114                _tbss_end = .;
    106         } :data
     115#endif
     116        } :data :tls
    107117       
     118#ifndef DLEXE
    108119        _tls_alignment = ALIGNOF(.tdata);
    109120#endif
  • uspace/lib/c/arch/ia32/include/libarch/rtld/elf_dyn.h

    raf2254ec rf356618  
    3636#define LIBC_ia32_RTLD_ELF_DYN_H_
    3737
    38 /* 
     38/*
    3939 * ia32 dynamic relocation types
    4040 */
     
    4747#define R_386_RELATIVE  8
    4848
     49#define R_386_TLS_TPOFF    14
    4950#define R_386_TLS_DTPMOD32 35
     51#define R_386_TLS_DTPOFF32 36
    5052
    5153#endif
  • uspace/lib/c/arch/ia32/include/libarch/tls.h

    raf2254ec rf356618  
    4343        void *self;
    4444        void *fibril_data;
     45        void **dtv;
    4546} tcb_t;
    4647
  • uspace/lib/c/arch/ia32/src/rtld/reloc.c

    raf2254ec rf356618  
    101101                        sym_def = symbol_def_find(str_tab + sym->st_name,
    102102                            m, ssf_none, &dest);
    103 //                      DPRINTF("dest name: '%s'\n", dest->dyn.soname);
     103                        DPRINTF("dest name: '%s'\n", dest->dyn.soname);
    104104//                      DPRINTF("dest bias: 0x%x\n", dest->bias);
    105105                        if (sym_def) {
    106106                                sym_addr = (uint32_t)
    107                                     symbol_get_addr(sym_def, dest);
     107                                    symbol_get_addr(sym_def, dest, NULL);
    108108//                              DPRINTF("symbol definition found, addr=0x%x\n", sym_addr);
    109109                        } else {
     
    115115                        sym_addr = 0;
    116116                        sym_def = NULL;
     117
     118                        /*
     119                         * DTPMOD with null st_name should return the index
     120                         * of the current module.
     121                         */
     122                        dest = m;
    117123                }
    118124
     
    148154                        if (sym_def) {
    149155                                sym_addr = (uint32_t)
    150                                     symbol_get_addr(sym_def, dest);
     156                                    symbol_get_addr(sym_def, dest, NULL);
    151157                        } else {
    152158                                printf("Source definition of '%s' not found.\n",
     
    171177                        break;
    172178
     179                case R_386_TLS_TPOFF:
     180                        DPRINTF("fixup R_386_TLS_TPOFF\n");
     181                        *r_ptr = (dest->ioffs + sym_def->st_value) - dest->rtld->tls_size;
     182                        break;
     183
     184                case R_386_TLS_DTPOFF32:
     185                        DPRINTF("fixup R_386_TLS_DTPOFF32\n");
     186                        *r_ptr = sym_def->st_value;
     187                        break;
     188
    173189                case R_386_TLS_DTPMOD32:
    174                         /*
    175                          * We can ignore this as long as the only module
    176                          * with TLS variables is libc.so.
    177                          */
    178                         DPRINTF("Ignoring R_386_TLS_DTPMOD32\n");
     190                        DPRINTF("fixup R_386_TLS_DTPMOD32\n");
     191                        *r_ptr = dest->id;
    179192                        break;
    180193
  • uspace/lib/c/arch/ia32/src/tls.c

    raf2254ec rf356618  
    11/*
    22 * Copyright (c) 2006 Ondrej Palkovsky
     3 * Copyright (c) 2016 Jiri Svoboda
    34 * All rights reserved.
    45 *
     
    3940#include <align.h>
    4041
     42#ifdef CONFIG_RTLD
     43#include <rtld/rtld.h>
     44#endif
     45
    4146tcb_t *tls_alloc_arch(void **data, size_t size)
    4247{
     
    6469    *___tls_get_addr(tls_index *ti)
    6570{
    66         size_t tls_size;
    6771        uint8_t *tls;
    6872
    69         /* Calculate size of TLS block */
    70         tls_size = ALIGN_UP(&_tbss_end - &_tdata_start, &_tls_alignment);
    71 
    72         /* The TLS block is just before TCB */
    73         tls = (uint8_t *)__tcb_get() - tls_size;
    74 
     73#ifdef CONFIG_RTLD
     74        if (runtime_env != NULL) {
     75                return rtld_tls_get_addr(runtime_env, __tcb_get(),
     76                    ti->ti_module, ti->ti_offset);
     77        }
     78#endif
     79        /* Get address of static TLS block */
     80        tls = tls_get();
    7581        return tls + ti->ti_offset;
    7682}
  • uspace/lib/c/generic/dlfcn.c

    raf2254ec rf356618  
    4949        module_t *m;
    5050
    51         if (runtime_env == NULL) {
    52                 printf("Dynamic linker not set up -- initializing.\n");
    53                 rtld_init_static();
    54         }
    55 
    56         printf("dlopen(\"%s\", %d)\n", path, flag);
    57 
    58         printf("module_find('%s')\n", path);
    5951        m = module_find(runtime_env, path);
    6052        if (m == NULL) {
    61                 printf("NULL. module_load('%s')\n", path);
    6253                m = module_load(runtime_env, path, mlf_local);
    63                 printf("module_load_deps(m)\n");
    6454                module_load_deps(m, mlf_local);
    6555                /* Now relocate. */
    66                 printf("module_process_relocs(m)\n");
    6756                module_process_relocs(m);
    68         } else {
    69                 printf("not NULL\n");
    7057        }
    7158
     
    8168        module_t *sm;
    8269
    83         printf("dlsym(0x%lx, \"%s\")\n", (long)mod, sym_name);
    8470        sd = symbol_bfs_find(sym_name, (module_t *) mod, &sm);
    8571        if (sd != NULL) {
    86                 return symbol_get_addr(sd, sm);
     72                return symbol_get_addr(sd, sm, __tcb_get());
    8773        }
    8874
  • uspace/lib/c/generic/elf/elf_mod.c

    raf2254ec rf356618  
    248248}
    249249
     250/** Process TLS program header.
     251 *
     252 * @param elf  Pointer to loader state buffer.
     253 * @param hdr  TLS program header
     254 * @param info Place to store TLS info
     255 */
     256static void tls_program_header(elf_ld_t *elf, elf_segment_header_t *hdr,
     257    elf_tls_info_t *info)
     258{
     259        info->tdata = (void *)((uint8_t *)hdr->p_vaddr + elf->bias);
     260        info->tdata_size = hdr->p_filesz;
     261        info->tbss_size = hdr->p_memsz - hdr->p_filesz;
     262        info->tls_align = hdr->p_align;
     263}
     264
    250265/** Process segment header.
    251266 *
     267 * @param elf   Pointer to loader state buffer.
    252268 * @param entry Segment header.
    253269 *
     
    277293        case 0x70000000:
    278294                /* FIXME: MIPS reginfo */
     295                break;
     296        case PT_TLS:
     297                /* Parse TLS program header */
     298                tls_program_header(elf, entry, &elf->info->tls);
     299                DPRINTF("TLS header found at %p\n",
     300                    (void *)((uint8_t *)entry->p_vaddr + elf->bias));
    279301                break;
    280302        case PT_SHLIB:
  • uspace/lib/c/generic/libc.c

    raf2254ec rf356618  
    4141 */
    4242
     43#include <errno.h>
    4344#include <libc.h>
    4445#include <stdlib.h>
     
    6869        __malloc_init();
    6970       
     71        /* Save the PCB pointer */
     72        __pcb = (pcb_t *) pcb_ptr;
     73       
     74#ifdef CONFIG_RTLD
     75        if (__pcb != NULL && __pcb->rtld_runtime != NULL) {
     76                runtime_env = (rtld_t *) __pcb->rtld_runtime;
     77        } else {
     78                if (rtld_init_static() != EOK)
     79                        abort();
     80        }
     81#endif
     82       
    7083        fibril_t *fibril = fibril_setup();
    7184        if (fibril == NULL)
     
    7487        __tcb_set(fibril->tcb);
    7588       
    76         /* Save the PCB pointer */
    77         __pcb = (pcb_t *) pcb_ptr;
    7889       
    7990#ifdef FUTEX_UPGRADABLE
     
    89100        char **argv;
    90101       
    91 #ifdef CONFIG_RTLD
    92         if (__pcb != NULL && __pcb->rtld_runtime != NULL) {
    93                 runtime_env = (rtld_t *) __pcb->rtld_runtime;
    94         }
    95 #endif
    96102        /*
    97103         * Get command line arguments and initialize
  • uspace/lib/c/generic/rtld/module.c

    raf2254ec rf356618  
    3737#include <adt/list.h>
    3838#include <elf/elf_load.h>
     39#include <errno.h>
    3940#include <fcntl.h>
    4041#include <loader/pcb.h>
     
    4849#include <rtld/rtld_arch.h>
    4950#include <rtld/module.h>
     51
     52/** Create module for static executable.
     53 *
     54 * @param rtld Run-time dynamic linker
     55 * @param rmodule Place to store pointer to new module or @c NULL
     56 * @return EOK on success, ENOMEM if out of memory
     57 */
     58int module_create_static_exec(rtld_t *rtld, module_t **rmodule)
     59{
     60        module_t *module;
     61
     62        module = calloc(1, sizeof(module_t));
     63        if (module == NULL)
     64                return ENOMEM;
     65
     66        module->id = rtld_get_next_id(rtld);
     67        module->dyn.soname = "[program]";
     68
     69        module->rtld = rtld;
     70        module->exec = true;
     71        module->local = true;
     72
     73        module->tdata = &_tdata_start;
     74        module->tdata_size = &_tdata_end - &_tdata_start;
     75        module->tbss_size = &_tbss_end - &_tbss_start;
     76        module->tls_align = (uintptr_t)&_tls_alignment;
     77
     78        list_append(&module->modules_link, &rtld->modules);
     79
     80        if (rmodule != NULL)
     81                *rmodule = module;
     82        return EOK;
     83}
    5084
    5185/** (Eagerly) process all relocation tables in a module.
     
    135169
    136170        m = calloc(1, sizeof(module_t));
    137         if (!m) {
     171        if (m == NULL) {
    138172                printf("malloc failed\n");
    139173                exit(1);
     
    141175
    142176        m->rtld = rtld;
     177        m->id = rtld_get_next_id(rtld);
     178
    143179        if ((flags & mlf_local) != 0)
    144180                m->local = true;
     
    181217        /* Insert into the list of loaded modules */
    182218        list_append(&m->modules_link, &rtld->modules);
     219
     220        /* Copy TLS info */
     221        m->tdata = info.tls.tdata;
     222        m->tdata_size = info.tls.tdata_size;
     223        m->tbss_size = info.tls.tbss_size;
     224        m->tls_align = info.tls.tls_align;
     225
     226        DPRINTF("tdata at %p size %zu, tbss size %zu\n",
     227            m->tdata, m->tdata_size, m->tbss_size);
    183228
    184229        return m;
     
    243288}
    244289
     290/** Find module structure by ID. */
     291module_t *module_by_id(rtld_t *rtld, unsigned long id)
     292{
     293        list_foreach(rtld->modules, modules_link, module_t, m) {
     294                if (m->id == id)
     295                        return m;
     296        }
     297
     298        return NULL;
     299}
     300
    245301/** Process relocations in modules.
    246302 *
     
    260316}
    261317
     318void modules_process_tls(rtld_t *rtld)
     319{
     320#ifdef CONFIG_TLS_VARIANT_1
     321        list_foreach(rtld->modules, modules_link, module_t, m) {
     322                m->ioffs = rtld->tls_size;
     323                list_append(&m->imodules_link, &rtmd->imodules);
     324                rtld->tls_size += m->tdata_size + m->tbss_size;
     325        }
     326#else /* CONFIG_TLS_VARIANT_2 */
     327        size_t offs;
     328
     329        list_foreach(rtld->modules, modules_link, module_t, m) {
     330                rtld->tls_size += m->tdata_size + m->tbss_size;
     331        }
     332
     333        offs = 0;
     334        list_foreach(rtld->modules, modules_link, module_t, m) {
     335                offs += m->tdata_size + m->tbss_size;
     336                m->ioffs = rtld->tls_size - offs;
     337                list_append(&m->imodules_link, &rtld->imodules);
     338        }
     339#endif
     340}
     341
    262342/** Clear BFS tags of all modules.
    263343 */
  • uspace/lib/c/generic/rtld/rtld.c

    raf2254ec rf356618  
    4343rtld_t *runtime_env;
    4444static rtld_t rt_env_static;
    45 static module_t prog_mod;
    4645
    4746/** Initialize the runtime linker for use in a statically-linked executable. */
    48 void rtld_init_static(void)
    49 {
     47int rtld_init_static(void)
     48{
     49        int rc;
     50
    5051        runtime_env = &rt_env_static;
    5152        list_initialize(&runtime_env->modules);
     53        list_initialize(&runtime_env->imodules);
    5254        runtime_env->next_bias = 0x2000000;
    5355        runtime_env->program = NULL;
     56        runtime_env->next_id = 1;
     57
     58        rc = module_create_static_exec(runtime_env, NULL);
     59        if (rc != EOK)
     60                return rc;
     61
     62        modules_process_tls(runtime_env);
     63
     64        return EOK;
    5465}
    5566
     
    6273{
    6374        rtld_t *env;
     75        module_t *prog;
    6476
    6577        DPRINTF("Load dynamically linked program.\n");
     
    7082                return ENOMEM;
    7183
     84        env->next_id = 1;
     85
     86        prog = calloc(1, sizeof(module_t));
     87        if (prog == NULL) {
     88                free(env);
     89                return ENOMEM;
     90        }
     91
    7292        /*
    7393         * First we need to process dynamic sections of the executable
     
    7696
    7797        DPRINTF("Parse program .dynamic section at %p\n", p_info->dynamic);
    78         dynamic_parse(p_info->dynamic, 0, &prog_mod.dyn);
    79         prog_mod.bias = 0;
    80         prog_mod.dyn.soname = "[program]";
    81         prog_mod.rtld = env;
    82         prog_mod.exec = true;
    83         prog_mod.local = false;
     98        dynamic_parse(p_info->dynamic, 0, &prog->dyn);
     99        prog->bias = 0;
     100        prog->dyn.soname = "[program]";
     101        prog->rtld = env;
     102        prog->id = rtld_get_next_id(env);
     103        prog->exec = true;
     104        prog->local = false;
     105
     106        prog->tdata = p_info->tls.tdata;
     107        prog->tdata_size = p_info->tls.tdata_size;
     108        prog->tbss_size = p_info->tls.tbss_size;
     109        prog->tls_align = p_info->tls.tls_align;
     110
     111        DPRINTF("prog tdata at %p size %zu, tbss size %zu\n",
     112            prog->tdata, prog->tdata_size, prog->tbss_size);
    84113
    85114        /* Initialize list of loaded modules */
    86115        list_initialize(&env->modules);
    87         list_append(&prog_mod.modules_link, &env->modules);
     116        list_initialize(&env->imodules);
     117        list_append(&prog->modules_link, &env->modules);
    88118
    89119        /* Pointer to program module. Used as root of the module graph. */
    90         env->program = &prog_mod;
     120        env->program = prog;
    91121
    92122        /* Work around non-existent memory space allocation. */
     
    98128
    99129        DPRINTF("Load all program dependencies\n");
    100         module_load_deps(&prog_mod, 0);
     130        module_load_deps(prog, 0);
     131
     132        /* Compute static TLS size */
     133        modules_process_tls(env);
    101134
    102135        /*
     
    106139        /* Process relocations in all modules */
    107140        DPRINTF("Relocate all modules\n");
    108         modules_process_relocs(env, &prog_mod);
     141        modules_process_relocs(env, prog);
    109142
    110143        *rre = env;
     
    112145}
    113146
     147/** Create TLS (Thread Local Storage) data structures.
     148 *
     149 * @return Pointer to TCB.
     150 */
     151tcb_t *rtld_tls_make(rtld_t *rtld)
     152{
     153        void *data;
     154        tcb_t *tcb;
     155        size_t offset;
     156        void **dtv;
     157        size_t nmods;
     158        size_t i;
     159
     160        tcb = tls_alloc_arch(&data, rtld->tls_size);
     161        if (tcb == NULL)
     162                return NULL;
     163
     164        /** Allocate dynamic thread vector */
     165        nmods = list_count(&rtld->imodules);
     166        dtv = malloc((nmods + 1) * sizeof(void *));
     167        if (dtv == NULL) {
     168                tls_free(tcb);
     169                return NULL;
     170        }
     171
     172        /*
     173         * We define generation number to be equal to vector length.
     174         * We start with a vector covering the initially loaded modules.
     175         */
     176        DTV_GN(dtv) = nmods;
     177
     178        /*
     179         * Copy thread local data from the initialization images of initial
     180         * modules. Zero out thread-local uninitialized data.
     181         */
     182
     183#ifdef CONFIG_TLS_VARIANT_1
     184        /*
     185         * Ascending addresses
     186         */
     187        offset = 0; i = 1;
     188        list_foreach(rtld->imodules, imodules_link, module_t, m) {
     189                assert(i == m->id);
     190                assert(offset + m->tdata_size + m->tbss_size <= rtld->tls_size);
     191                dtv[i++] = data + offset;
     192                memcpy(data + offset, m->tdata, m->tdata_size);
     193                offset += m->tdata_size;
     194                memset(data + offset, 0, m->tbss_size);
     195                offset += m->tbss_size;
     196        }
     197#else /* CONFIG_TLS_VARIANT_2 */
     198        /*
     199         * Descending addresses
     200         */
     201        offset = 0; i = 1;
     202        list_foreach(rtld->imodules, imodules_link, module_t, m) {
     203                assert(i == m->id);
     204                assert(offset + m->tdata_size + m->tbss_size <= rtld->tls_size);
     205                offset += m->tbss_size;
     206                memset(data + rtld->tls_size - offset, 0, m->tbss_size);
     207                offset += m->tdata_size;
     208                memcpy(data + rtld->tls_size - offset, m->tdata, m->tdata_size);
     209                dtv[i++] = data + rtld->tls_size - offset;
     210        }
     211#endif
     212
     213        tcb->dtv = dtv;
     214        return tcb;
     215}
     216
     217unsigned long rtld_get_next_id(rtld_t *rtld)
     218{
     219        return rtld->next_id++;
     220}
     221
     222/** Get address of thread-local variable.
     223 *
     224 * @param rtld RTLD instance
     225 * @param tcb TCB of the thread whose instance to return
     226 * @param mod_id Module ID
     227 * @param offset Offset within TLS block of the module
     228 *
     229 * @return Address of thread-local variable
     230 */
     231void *rtld_tls_get_addr(rtld_t *rtld, tcb_t *tcb, unsigned long mod_id,
     232    unsigned long offset)
     233{
     234        module_t *m;
     235        size_t dtv_len;
     236        void *tls_block;
     237
     238        dtv_len = DTV_GN(tcb->dtv);
     239        if (dtv_len < mod_id) {
     240                /* Vector is short */
     241
     242                tcb->dtv = realloc(tcb->dtv, (1 + mod_id) * sizeof(void *));
     243                /* XXX This can fail if OOM */
     244                assert(tcb->dtv != NULL);
     245                /* Zero out new part of vector */
     246                memset(tcb->dtv + (1 + dtv_len), 0, (mod_id - dtv_len) *
     247                    sizeof(void *));
     248        }
     249
     250        if (tcb->dtv[mod_id] == NULL) {
     251                /* TLS block is not allocated */
     252
     253                m = module_by_id(rtld, mod_id);
     254                assert(m != NULL);
     255                /* Should not be initial module, those have TLS pre-allocated */
     256                assert(!link_used(&m->imodules_link));
     257
     258                tls_block = malloc(m->tdata_size + m->tbss_size);
     259                /* XXX This can fail if OOM */
     260                assert(tls_block != NULL);
     261
     262                /* Copy tdata */
     263                memcpy(tls_block, m->tdata, m->tdata_size);
     264                /* Zero out tbss */
     265                memset(tls_block + m->tdata_size, 0, m->tbss_size);
     266
     267                tcb->dtv[mod_id] = tls_block;
     268        }
     269
     270        return (uint8_t *)(tcb->dtv[mod_id]) + offset;
     271}
     272
    114273/** @}
    115274 */
  • uspace/lib/c/generic/rtld/symbol.c

    raf2254ec rf356618  
    249249}
    250250
    251 void *symbol_get_addr(elf_symbol_t *sym, module_t *m)
    252 {
    253         if (sym->st_shndx == SHN_ABS) {
     251/** Get symbol address.
     252 *
     253 * @param sym Symbol
     254 * @param m Module contaning the symbol
     255 * @param tcb TCB of the thread whose thread-local variable instance should
     256 *            be returned. If @a tcb is @c NULL then @c NULL is returned for
     257 *            thread-local variables.
     258 *
     259 * @return Symbol address
     260 */
     261void *symbol_get_addr(elf_symbol_t *sym, module_t *m, tcb_t *tcb)
     262{
     263        if (ELF_ST_TYPE(sym->st_info) == STT_TLS) {
     264                if (tcb == NULL)
     265                        return NULL;
     266                return rtld_tls_get_addr(m->rtld, tcb, m->id, sym->st_value);
     267        } else if (sym->st_shndx == SHN_ABS) {
    254268                /* Do not add bias to absolute symbols */
    255269                return (void *) sym->st_value;
  • uspace/lib/c/generic/tls.c

    raf2254ec rf356618  
    3434 * Support for thread-local storage, as described in:
    3535 *      Drepper U.: ELF Handling For Thread-Local Storage, 2005
    36  *
    37  * Only static model is supported.
    38  */
     36 */
    3937
    4038#include <tls.h>
    4139#include <malloc.h>
    4240#include <str.h>
    43 #include <align.h>
    4441#include <unistd.h>
    4542
     43#ifdef CONFIG_RTLD
     44#include <rtld/rtld.h>
     45#endif
     46
     47size_t tls_get_size(void)
     48{
     49#ifdef CONFIG_RTLD
     50        if (runtime_env != NULL)
     51                return runtime_env->tls_size;
     52#endif
     53        return &_tbss_end - &_tdata_start;
     54}
     55
     56/** Get address of static TLS block */
     57void *tls_get(void)
     58{
     59#ifdef CONFIG_TLS_VARIANT_1
     60        return (uint8_t *)__tcb_get() + sizeof(tcb_t);
     61#else /* CONFIG_TLS_VARIANT_2 */
     62        return (uint8_t *)__tcb_get() - tls_get_size();
     63#endif
     64}
     65
    4666/** Create TLS (Thread Local Storage) data structures.
    47  *
    48  * The code requires, that sections .tdata and .tbss are adjacent. It may be
    49  * changed in the future.
    5067 *
    5168 * @return Pointer to TCB.
     
    5673        tcb_t *tcb;
    5774        size_t tls_size = &_tbss_end - &_tdata_start;
    58        
     75
     76#ifdef CONFIG_RTLD
     77        if (runtime_env != NULL)
     78                return rtld_tls_make(runtime_env);
     79#endif
    5980        tcb = tls_alloc_arch(&data, tls_size);
    6081        if (!tcb)
    6182                return NULL;
    62        
     83
    6384        /*
    6485         * Copy thread local data from the initialization image.
     
    7697void tls_free(tcb_t *tcb)
    7798{
    78         size_t tls_size = &_tbss_end - &_tdata_start;
    79         tls_free_arch(tcb, tls_size);
     99#ifdef CONFIG_RTLD
     100        free(tcb->dtv);
     101#endif
     102        tls_free_arch(tcb, tls_get_size());
    80103}
    81104
     
    89112tcb_t *tls_alloc_variant_1(void **data, size_t size)
    90113{
    91         tcb_t *result;
     114        tcb_t *tcb;
    92115
    93         result = malloc(sizeof(tcb_t) + size);
    94         if (!result)
     116        tcb = malloc(sizeof(tcb_t) + size);
     117        if (!tcb)
    95118                return NULL;
    96         *data = ((void *)result) + sizeof(tcb_t);
     119        *data = ((void *)tcb) + sizeof(tcb_t);
     120#ifdef CONFIG_RTLD
     121        tcb->dtv = NULL;
     122#endif
    97123
    98         return result;
     124        return tcb;
    99125}
    100126
     
    121147{
    122148        tcb_t *tcb;
    123        
    124         size = ALIGN_UP(size, &_tls_alignment);
    125         *data = memalign((uintptr_t) &_tls_alignment, sizeof(tcb_t) + size);
    126         if (!*data)
     149
     150        *data = malloc(sizeof(tcb_t) + size);
     151        if (*data == NULL)
    127152                return NULL;
    128153        tcb = (tcb_t *) (*data + size);
    129154        tcb->self = tcb;
     155#ifdef CONFIG_RTLD
     156        tcb->dtv = NULL;
     157#endif
    130158
    131159        return tcb;
     
    139167void tls_free_variant_2(tcb_t *tcb, size_t size)
    140168{
    141         size = ALIGN_UP(size, &_tls_alignment);
    142169        void *start = ((void *) tcb) - size;
    143170        free(start);
  • uspace/lib/c/include/elf/elf_mod.h

    raf2254ec rf356618  
    5858} eld_flags_t;
    5959
     60/** TLS info for a module */
     61typedef struct {
     62        /** tdata section image */
     63        void *tdata;
     64        /** Size of tdata section image in bytes */
     65        size_t tdata_size;
     66        /** Size of tbss section */
     67        size_t tbss_size;
     68        /** Alignment of TLS initialization image */
     69        size_t tls_align;
     70} elf_tls_info_t;
     71
    6072/**
    6173 * Some data extracted from the headers are stored here
     
    7082        /** Pointer to the dynamic section */
    7183        void *dynamic;
     84
     85        /** TLS info */
     86        elf_tls_info_t tls;
    7287} elf_finfo_t;
    7388
  • uspace/lib/c/include/rtld/module.h

    raf2254ec rf356618  
    4242#include <types/rtld/rtld.h>
    4343
     44extern int module_create_static_exec(rtld_t *, module_t **);
    4445extern void module_process_relocs(module_t *);
    4546extern module_t *module_find(rtld_t *, const char *);
    4647extern module_t *module_load(rtld_t *, const char *, mlflags_t);
    4748extern void module_load_deps(module_t *, mlflags_t);
     49extern module_t *module_by_id(rtld_t *, unsigned long);
    4850
    4951extern void modules_process_relocs(rtld_t *, module_t *);
     52extern void modules_process_tls(rtld_t *);
    5053extern void modules_untag(rtld_t *);
    5154
  • uspace/lib/c/include/rtld/rtld.h

    raf2254ec rf356618  
    4141
    4242#include <rtld/dynamic.h>
     43#include <tls.h>
    4344#include <types/rtld/rtld.h>
    4445
    4546extern rtld_t *runtime_env;
    4647
    47 extern void rtld_init_static(void);
     48extern int rtld_init_static(void);
    4849extern int rtld_prog_process(elf_finfo_t *, rtld_t **);
     50extern tcb_t *rtld_tls_make(rtld_t *);
     51extern unsigned long rtld_get_next_id(rtld_t *);
     52extern void *rtld_tls_get_addr(rtld_t *, tcb_t *, unsigned long, unsigned long);
    4953
    5054#endif
  • uspace/lib/c/include/rtld/symbol.h

    raf2254ec rf356618  
    3838#include <elf/elf.h>
    3939#include <rtld/rtld.h>
     40#include <tls.h>
    4041
    4142/** Symbol search flags */
     
    5051extern elf_symbol_t *symbol_def_find(const char *, module_t *,
    5152    symbol_search_flags_t, module_t **);
    52 extern void *symbol_get_addr(elf_symbol_t *, module_t *);
     53extern void *symbol_get_addr(elf_symbol_t *, module_t *, tcb_t *);
    5354
    5455#endif
  • uspace/lib/c/include/tls.h

    raf2254ec rf356618  
    3939#include <sys/types.h>
    4040
     41/** DTV Generation number - equals vector length */
     42#define DTV_GN(dtv) (((uintptr_t *)(dtv))[0])
     43
    4144/*
    4245 * Symbols defined in the respective linker script.
     
    5255extern void tls_free(tcb_t *);
    5356extern void tls_free_arch(tcb_t *, size_t);
     57extern size_t tls_get_size(void);
     58extern void *tls_get(void);
    5459
    5560#ifdef CONFIG_TLS_VARIANT_1
  • uspace/lib/c/include/types/rtld/module.h

    raf2254ec rf356618  
    4646/** Dynamically linked module */
    4747typedef struct module {
     48        /** Module ID */
     49        unsigned long id;
     50        /** Dynamic info for this module */
    4851        dyn_info_t dyn;
     52        /** Load bias */
    4953        size_t bias;
     54
     55        /** tdata image start */
     56        void *tdata;
     57        /** tdata image size */
     58        size_t tdata_size;
     59        /** tbss size */
     60        size_t tbss_size;
     61        /** TLS alignment */
     62        size_t tls_align;
     63
     64        size_t ioffs;
    5065
    5166        /** Containing rtld */
     
    6176        /** Link to list of all modules in runtime environment */
    6277        link_t modules_link;
     78        /** Link to list of initial modules */
     79        link_t imodules_link;
    6380
    6481        /** Link to BFS queue. Only used when doing a BFS of the module graph */
  • uspace/lib/c/include/types/rtld/rtld.h

    raf2254ec rf356618  
    4848        module_t *program;
    4949
     50        /** Next module ID */
     51        unsigned long next_id;
     52
     53        /** Size of initial TLS tdata + tbss */
     54        size_t tls_size;
     55
    5056        /** List of all loaded modules including rtld and the program */
    5157        list_t modules;
     58
     59        /** List of initial modules */
     60        list_t imodules;
    5261
    5362        /** Temporary hack to place each module at different address. */
  • uspace/lib/dltest/dltest.c

    raf2254ec rf356618  
    3434 */
    3535
     36#include <fibril.h>
    3637#include "libdltest.h"
    3738
     
    4546/** Public uninitialized variable */
    4647int dl_public_uvar;
     48
     49/** Private initialized fibril-local variable */
     50static fibril_local int dl_private_fib_var = dl_private_fib_var_val;
     51/** Private uninitialized fibril-local variable */
     52static fibril_local int dl_private_fib_uvar;
     53
     54/** Public initialized fibril-local variable */
     55fibril_local int dl_public_fib_var = dl_public_fib_var_val;
     56/** Public uninitialized fibril-local variable */
     57fibril_local int dl_public_fib_uvar;
    4758
    4859/** Return constant value. */
     
    5869}
    5970
     71/** Return address of private initialized variable */
     72int *dl_get_private_var_addr(void)
     73{
     74        return &private_var;
     75}
     76
    6077/** Return value of private uninitialized variable */
    6178int dl_get_private_uvar(void)
    6279{
    6380        return private_uvar;
     81}
     82
     83/** Return vaddress of private uninitialized variable */
     84int *dl_get_private_uvar_addr(void)
     85{
     86        return &private_uvar;
    6487}
    6588
     
    7093}
    7194
     95/** Return address of public initialized variable */
     96int *dl_get_public_var_addr(void)
     97{
     98        return &dl_public_var;
     99}
     100
    72101/** Return value of public uninitialized variable */
    73102int dl_get_public_uvar(void)
     
    76105}
    77106
     107/** Return address of public uninitialized variable */
     108int *dl_get_public_uvar_addr(void)
     109{
     110        return &dl_public_uvar;
     111}
     112
     113/** Return value of private initialized fibril-local variable */
     114int dl_get_private_fib_var(void)
     115{
     116        return dl_private_fib_var;
     117}
     118
     119/** Return address of private initialized fibril-local variable */
     120int *dl_get_private_fib_var_addr(void)
     121{
     122        return &dl_private_fib_var;
     123}
     124
     125/** Return value of private uninitialized fibril-local variable */
     126int dl_get_private_fib_uvar(void)
     127{
     128        return dl_private_fib_uvar;
     129}
     130
     131/** Return address of private uninitialized fibril-local variable */
     132int *dl_get_private_fib_uvar_addr(void)
     133{
     134        return &dl_private_fib_uvar;
     135}
     136
     137/** Return value of public initialized fibril-local variable */
     138int dl_get_public_fib_var(void)
     139{
     140        return dl_public_fib_var;
     141}
     142
     143/** Return value of public initialized fibril-local variable */
     144int *dl_get_public_fib_var_addr(void)
     145{
     146        return &dl_public_fib_var;
     147}
     148
     149/** Return value of public uninitialized fibril-local variable */
     150int dl_get_public_fib_uvar(void)
     151{
     152        return dl_public_fib_uvar;
     153}
     154
     155/** Return value of public uninitialized fibril-local variable */
     156int *dl_get_public_fib_uvar_addr(void)
     157{
     158        return &dl_public_fib_uvar;
     159}
     160
    78161/**
    79162 * @}
  • uspace/lib/dltest/libdltest.h

    raf2254ec rf356618  
    3737#define LIBDLTEST_H
    3838
     39#include <fibril.h>
     40
    3941enum {
    4042        dl_constant = 110011,
    4143        dl_private_var_val = 220022,
    42         dl_public_var_val = 330033
     44        dl_public_var_val = 330033,
     45        dl_private_fib_var_val = 440044,
     46        dl_public_fib_var_val = 550055
    4347};
    4448
    4549extern int dl_get_constant(void);
    4650extern int dl_get_private_var(void);
     51extern int *dl_get_private_var_addr(void);
    4752extern int dl_get_private_uvar(void);
     53extern int *dl_get_private_uvar_addr(void);
    4854extern int dl_get_public_var(void);
     55extern int *dl_get_public_var_addr(void);
    4956extern int dl_get_public_uvar(void);
     57extern int *dl_get_public_uvar_addr(void);
     58extern int dl_get_private_fib_var(void);
     59extern int *dl_get_private_fib_var_addr(void);
     60extern int dl_get_private_fib_uvar(void);
     61extern int *dl_get_private_fib_uvar_addr(void);
     62extern int dl_get_public_fib_var(void);
     63extern int *dl_get_public_fib_var_addr(void);
     64extern int dl_get_public_fib_uvar(void);
     65extern int *dl_get_public_fib_uvar_addr(void);
    5066
    5167extern int dl_public_var;
    5268extern int dl_public_uvar;
     69extern fibril_local int dl_public_fib_var;
     70extern fibril_local int dl_public_fib_uvar;
    5371
    5472#endif
  • uspace/srv/loader/main.c

    raf2254ec rf356618  
    269269       
    270270        pcb.filc = filc;
    271         printf("dynamic=%p rtld_env=%p\n", pcb.dynamic, pcb.rtld_runtime);
    272271       
    273272        async_answer_0(rid, rc);
Note: See TracChangeset for help on using the changeset viewer.