IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    RISC-V TLSDESC works!

    MaskRay发表于 2024-01-23 09:04:58
    love 0

    I'll make this post more polished.

    Patch musl per Re: Draftriscv64 TLSDESC implementation

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    diff --git c/arch/riscv64/reloc.h w/arch/riscv64/reloc.h
    index 1ca13811..7c7c0611 100644
    --- c/arch/riscv64/reloc.h
    +++ w/arch/riscv64/reloc.h
    @@ -17,6 +17,7 @@
    #define REL_DTPMOD R_RISCV_TLS_DTPMOD64
    #define REL_DTPOFF R_RISCV_TLS_DTPREL64
    #define REL_TPOFF R_RISCV_TLS_TPREL64
    +#define REL_TLSDESC R_RISCV_TLSDESC

    #define CRTJMP(pc,sp) __asm__ __volatile__( \
    "mv sp, %1 ; jr %0" : : "r"(pc), "r"(sp) : "memory" )
    diff --git c/include/elf.h w/include/elf.h
    index 72d17c3a..7f342a23 100644
    --- c/include/elf.h
    +++ w/include/elf.h
    @@ -3254,6 +3254,7 @@ enum
    #define R_RISCV_TLS_DTPREL64 9
    #define R_RISCV_TLS_TPREL32 10
    #define R_RISCV_TLS_TPREL64 11
    +#define R_RISCV_TLSDESC 12

    #define R_RISCV_BRANCH 16
    #define R_RISCV_JAL 17
    diff --git c/src/ldso/riscv64/tlsdesc.s w/src/ldso/riscv64/tlsdesc.s
    new file mode 100644
    index 00000000..56d1ce89
    --- /dev/null
    +++ w/src/ldso/riscv64/tlsdesc.s
    @@ -0,0 +1,33 @@
    +.text
    +.global __tlsdesc_static
    +.hidden __tlsdesc_static
    +.type __tlsdesc_static,%function
    +__tlsdesc_static:
    + ld a0,8(a0)
    + jr t0
    +
    +.global __tlsdesc_dynamic
    +.hidden __tlsdesc_dynamic
    +.type __tlsdesc_dynamic,%function
    +__tlsdesc_dynamic:
    + add sp,sp,-16
    + sd t1,(sp)
    + sd t2,8(sp)
    +
    + ld t2,-8(tp) # t2=dtv
    +
    + ld a0,8(a0) # a0=&{modidx,off}
    + ld t1,8(a0) # t1=off
    + ld a0,(a0) # a0=modidx
    + sll a0,a0,3 # a0=8*modidx
    +
    + add a0,a0,t2 # a0=dtv+8*modidx
    + ld a0,(a0) # a0=dtv[modidx]
    + add a0,a0,t1 # a0=dtv[modidx]+off
    + sub a0,a0,tp # a0=dtv[modidx]+off-tp
    +
    + ld t1,(sp)
    + ld t2,8(sp)
    + add sp,sp,16
    + jr t0
    +

    1
    (mkdir -p out/rv64 && cd out/rv64 && ../../configure --target=riscv64-linux-gnu && make -j 50)

    Adjust ~/musl/out/rv64/lib/musl-gcc.specs and update~/musl/out/rv64/obj/musl-gcc

    1
    2
    3
    4
    cat > ~/musl/out/rv64/obj/musl-gcc <<eof
    #!/bin/sh
    exec "${REALGCC:-riscv64-linux-gnu-gcc}" "$@" -specs ~/musl/out/rv64/lib/musl-gcc.specs
    eof

    Prepare a runtime test mentioned at the end of https://maskray.me/blog/2021-02-14-all-about-thread-local-storage

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    cat > ./a.c <<eof
    #include <assert.h>
    int foo();
    int bar();
    int main() {
    assert(foo() == 2);
    assert(foo() == 4);
    assert(bar() == 2);
    assert(bar() == 4);
    }
    eof

    cat > ./b.c <<eof
    #include <stdio.h>
    __thread int tls0;
    extern __thread int tls1;
    int foo() { return ++tls0 + ++tls1; }
    static __thread int tls2, tls3;
    int bar() { return ++tls2 + ++tls3; }
    eof

    echo '__thread int tls1;' > ./c.c

    sed 's/ /\t/' > ./Makefile <<'eof'
    .MAKE.MODE = meta curDirOk=true

    CC := ~/musl/out/rv64/obj/musl-gcc -O1 -g -fpic -Bbin -fuse-ld=lld
    LDFLAGS := -Wl,-rpath=.

    all: a0 a1 a2

    run: all
    ./a0 && ./a1 && ./a2

    b.o: bb.s
    /tmp/Rel/bin/clang --target=riscv64-linux -c bb.s -o $@
    c.so: c.o; ${LINK.c} -shared $> -o $@
    bc.so: b.o c.o; ${LINK.c} -shared $> -o $@
    b.so: b.o c.so; ${LINK.c} -shared $> -o $@

    a0: a.o b.o c.o; ${LINK.c} $> -o $@
    a1: a.o b.so; ${LINK.c} $> -o $@
    a2: a.o bc.so; ${LINK.c} $> -o $@
    eof

    Compile b.c to bb.s. Replacegeneral-dynamic code sequences (e.g.la.tls.gd a0,tls0; call __tls_get_addr@plt) with TLSDESC,e.g.

    1
    2
    3
    4
    5
    6
    .Ltlsdesc_hi0:
    auipc a0, %tlsdesc_hi(tls0)
    ld a1, %tlsdesc_load_lo(.Ltlsdesc_hi0)(a0)
    addi a0, a0, %tlsdesc_add_lo(.Ltlsdesc_hi0)
    jalr t0, 0(a1), %tlsdesc_call(.Ltlsdesc_hi0)
    add a0, a0, tp

    Apply LLVM CodeGen/assembly and lld patch (https://github.com/llvm/llvm-project/pull/79099) tollvm-project. Build clang and lld. Create an aliasbin/ld.lld to be used with-Bbin -fuse-ld=lld.

    bmake run => succeeded!

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    % bmake run
    ~/musl/out/rv64/obj/musl-gcc -O1 -g -fpic -Bbin -fuse-ld=lld -g -c a.c
    /tmp/Rel/bin/clang --target=riscv64-linux -c bb.s -o b.o
    ~/musl/out/rv64/obj/musl-gcc -O1 -g -fpic -Bbin -fuse-ld=lld -g -c c.c
    ~/musl/out/rv64/obj/musl-gcc -O1 -g -fpic -Bbin -fuse-ld=lld -g -Wl,-rpath=. a.o b.o c.o -o a0
    ~/musl/out/rv64/obj/musl-gcc -O1 -g -fpic -Bbin -fuse-ld=lld -g -Wl,-rpath=. -shared c.o -o c.so
    ~/musl/out/rv64/obj/musl-gcc -O1 -g -fpic -Bbin -fuse-ld=lld -g -Wl,-rpath=. -shared b.o c.so -o b.so
    ~/musl/out/rv64/obj/musl-gcc -O1 -g -fpic -Bbin -fuse-ld=lld -g -Wl,-rpath=. a.o b.so -o a1
    ~/musl/out/rv64/obj/musl-gcc -O1 -g -fpic -Bbin -fuse-ld=lld -g -Wl,-rpath=. -shared b.o c.o -o bc.so
    ~/musl/out/rv64/obj/musl-gcc -O1 -g -fpic -Bbin -fuse-ld=lld -g -Wl,-rpath=. a.o bc.so -o a2
    ./a0 && ./a1 && ./a2


沪ICP备19023445号-2号
友情链接