rv64_tls_link.sh (3647B)
1 #!/usr/bin/env bash 2 # test/smoke/rv64_tls_link.sh — regression for rv64 TLS Local-Exec lowering, on 3 # the shared corpus harness (test/lib/kit_corpus.sh). 4 # 5 # rv64 used to emit R_RV_TLS_GOT_HI20 (Initial-Exec) for an extern 6 # _Thread_local symbol under -fPIE (the hosted default). The linker has no 7 # layout/apply for that reloc, so linking failed hard with 8 # "link: unsupported reloc kind 80" instead of producing a binary. kit 9 # links whole-module/static, so the fix is to always emit Local-Exec 10 # (R_RISCV_TPREL_HI20/LO12_I), matching the aa64 and x64 backends. 11 # 12 # This is link-only (no execution), so it runs on any host without qemu. It is 13 # a single synthetic structural case: one lane (L) that compiles two sources, 14 # asserts the extern _Thread_local access lowered to TPREL (and NOT TLS_GOT) by 15 # grepping `objdump -r` BEFORE linking, then asserts the whole-module link 16 # succeeds. The L0 (reloc-presence) checks intentionally precede the link. 17 18 set -u 19 ROOT="$(cd "$(dirname "$0")/../.." && pwd)" 20 KIT="${KIT:-$ROOT/build/kit}" 21 BUILD_DIR="$ROOT/build/test/rv64-tls-link" 22 mkdir -p "$BUILD_DIR" 23 24 # Preserve the original pass-through skip: when kit is not built, this 25 # regression simply cannot run, and that is reported as a clean exit 0 (it is 26 # not a degraded run — the binary just isn't there yet). 27 if [ ! -x "$KIT" ]; then 28 echo "SKIP rv64_tls_link: $KIT not built" 29 exit 0 30 fi 31 32 export KIT_LIB_DIR="$ROOT/test/lib" 33 # shellcheck source=../lib/kit_corpus.sh 34 . "$ROOT/test/lib/kit_corpus.sh" 35 36 # Single synthetic case: a marker file the engine can discover so the lane 37 # fires exactly once. All real artifacts are generated under $KIT_WORK. 38 CASE_DIR="$BUILD_DIR/case" 39 mkdir -p "$CASE_DIR" 40 : > "$CASE_DIR/rv64_tls_link.case" 41 42 # ---- lane L: compile -> objdump -r reloc presence/absence -> link ---------- 43 # Keeps the L0-before-link ordering: the reloc oracle runs on the compiled .o 44 # before the whole-module link is attempted. 45 kit_lane_L() { 46 cat > "$KIT_WORK/tls_def.c" <<'EOF' 47 _Thread_local int g = 7; 48 EOF 49 cat > "$KIT_WORK/tls_ie.c" <<'EOF' 50 extern _Thread_local int g; 51 int read_g(void) { return g; } 52 int *addr_g(void) { return &g; } 53 EOF 54 55 if ! "$KIT" cc -c -target riscv64-linux "$KIT_WORK/tls_ie.c" \ 56 -o "$KIT_WORK/tls_ie.o" >"$KIT_WORK/cc_ie.out" 2>"$KIT_WORK/cc_ie.err"; then 57 kit_fail "$KIT_NAME" "compile tls_ie.c"; return 58 fi 59 if ! "$KIT" cc -c -target riscv64-linux "$KIT_WORK/tls_def.c" \ 60 -o "$KIT_WORK/tls_def.o" >"$KIT_WORK/cc_def.out" 2>"$KIT_WORK/cc_def.err"; then 61 kit_fail "$KIT_NAME" "compile tls_def.c"; return 62 fi 63 64 # The extern _Thread_local access must lower to TPREL, never TLS_GOT. 65 local relocs 66 relocs="$("$KIT" objdump -r "$KIT_WORK/tls_ie.o" 2>&1)" 67 if ! printf '%s\n' "$relocs" | grep -q 'R_RISCV_TPREL_HI20'; then 68 kit_fail "$KIT_NAME" "expected R_RISCV_TPREL_HI20 reloc; got: $relocs"; return 69 fi 70 if printf '%s\n' "$relocs" | grep -q 'TLS_GOT'; then 71 kit_fail "$KIT_NAME" "unexpected TLS_GOT reloc (Initial-Exec regressed): $relocs"; return 72 fi 73 74 # And the whole-module link must succeed (previously: unsupported reloc 80). 75 if ! "$KIT" ld --entry read_g "$KIT_WORK/tls_ie.o" "$KIT_WORK/tls_def.o" \ 76 -o "$KIT_WORK/tls_out" >"$KIT_WORK/ld.out" 2>"$KIT_WORK/ld.err"; then 77 kit_fail "$KIT_NAME" "link extern _Thread_local"; return 78 fi 79 80 kit_pass "$KIT_NAME" 81 } 82 83 KIT_LABEL=rv64_tls_link KIT_BUILD_DIR="$BUILD_DIR/work" \ 84 KIT_CORPUS_GLOBS="$CASE_DIR/*.case" KIT_CORPUS_EXT=case KIT_SIDECAR_DIR="$CASE_DIR" \ 85 KIT_LANES="L" KIT_OPT_LEVELS="" KIT_TUPLES="rv64-elf" KIT_TARGETS_EXT="" \ 86 KIT_PARALLELIZABLE=0 kit_corpus_run 87 88 kit_summary rv64_tls_link 89 kit_exit