brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.7 KiB · 25e30b4 Raw
101 lines · plain
1# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s2 3## A `.tdata` (initialised thread-local) pointer initialised to the address of a4## non-TLS global -- the `__thread T *p = &global;` shape (e.g. glibc's5## `__thread locale_t __libc_tsd_LOCALE = &_nl_global_locale;`).  The initialiser6## is a non-PIC link-time-constant address carried by an R_WASM_MEMORY_ADDR_I327## relocation inside the .tdata segment.8##9## Such a relocation must be applied BOTH ways:10##   (1) baked into the .tdata template image bytes (the per-thread copy source),11##   (2) emitted into __wasm_apply_tls_relocs so the value is (re)applied to the12##       live per-thread TLS block at runtime -- __wasm_init_tls calls it.13##14## Before the fix, __wasm_apply_tls_relocs only emitted code for PIC/GOT15## relocations, so a non-PIC absolute TLS relocation was silently dropped and the16## function was a 3-byte no-op (just `end`).  A libc that establishes the17## per-thread block by zero-filling it rather than copying the wasm passive18## template verbatim (glibc's _dl_allocate_tls_init memsets the block because a19## wasm TLS segment has no linear init-image) then leaves the `.tdata` pointer20## slot NULL: a silent miscompile.  The checks below assert the store is emitted21## (it is absent pre-fix -> RED, present post-fix -> GREEN) and that the template22## image still carries the baked constant.23 24.globaltype __tls_base, i3225 26## Keep `tp` live (referenced through an initial-exec-style TLS access).27.text28.globl tp_addr29tp_addr:30  .functype tp_addr () -> (i32)31  global.get __tls_base32  i32.const tp@TLSREL33  i32.add34  end_function35 36## A non-TLS global; the thread-local pointer below is initialised to its address.37.section .data.g,"",@38.globl g39.p2align 240g:41  .int32 123442  .size g, 443 44## `__thread int *tp = &g;` -- a .tdata pointer initialised to &g.  Emits an45## R_WASM_MEMORY_ADDR_I32 relocation (a non-PIC absolute address) at TLS offset 0.46.section .tdata.tp,"T",@47.globl tp48.p2align 249tp:50  .int32 g51  .size tp, 452 53.section  .custom_section.target_features,"",@54  .int8 255  .int8 4356  .int8 757  .ascii  "atomics"58  .int8 4359  .int8 1160  .ascii  "bulk-memory"61 62# RUN: wasm-ld -no-gc-sections --shared-memory --max-memory=131072 --no-entry -o %t.wasm %t.o63# RUN: llvm-objdump -d --no-show-raw-insn --no-leading-addr %t.wasm | FileCheck --check-prefix=ASM %s64# RUN: obj2yaml %t.wasm | FileCheck --check-prefix=YAML %s65 66## __wasm_init_tls must materialise the per-thread block (memory.init of the67## passive .tdata template) AND call __wasm_apply_tls_relocs.68# ASM-LABEL: <__wasm_init_tls>:69# ASM-EMPTY:70# ASM-NEXT:    local.get 071# ASM-NEXT:    global.set 172# ASM-NEXT:    local.get 073# ASM-NEXT:    i32.const 074# ASM-NEXT:    i32.const 475# ASM-NEXT:    memory.init 0, 076# ASM-NEXT:    call [[APPLY:[0-9]+]]77# ASM-NEXT:    end78 79## GREEN assertion: __wasm_apply_tls_relocs applies the non-PIC absolute TLS80## relocation by storing &g into the live slot __tls_base + 0.  Pre-fix this81## function body was empty (just `end`), so the `global.get 1` line below is82## absent and FileCheck fails -- the RED arm.83# ASM-LABEL: <__wasm_apply_tls_relocs>:84# ASM-EMPTY:85# ASM-NEXT:    global.get 186# ASM-NEXT:    i32.const 087# ASM-NEXT:    i32.add88# ASM-NEXT:    i32.const [[ADDR:[0-9]+]]89# ASM-NEXT:    i32.store90# ASM-NEXT:    end91 92## The .tdata template image must ALSO carry the baked constant &g (little-endian93## 4-byte pointer): .tdata is the first data segment, tp is at TLS offset 0, and94## g is placed right after it, so &g == .tdata base + 4 and the image bytes are95## the little-endian encoding of that address.96# YAML:      - Type:            DATA{{$}}97# YAML-NEXT:    Segments:98# YAML-NEXT:      - SectionOffset:   {{.*}}99# YAML-NEXT:        InitFlags:       1100# YAML-NEXT:        Content:         {{'?}}04000100{{'?}}101