[llvm-branch-commits] [lld] ELF: CFI jump table relaxation. (PR #147424)
Fangrui Song via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sat May 2 18:01:29 PDT 2026
MaskRay wrote:
Script that demonstrates the end-to-end behavior difference
```sh
cat > cfi.cc <<'eof'
// CFI icall example -- function pointer indirect calls trigger jump tables.
extern "C" {
// Tiny: ret-only body, fits in 8 bytes.
int tiny1(int) { return 1; }
int tiny2(int) { return 2; }
// Big: too large to inline into a single 8-byte slot.
int big(int x) {
int s = 0;
for (int i = 0; i < 7; ++i) s += i * x;
return s;
}
// Force the address of each function to be taken so a jump table is built.
typedef int (*FP)(int);
__attribute__((noinline))
int call(FP fp, int x) { return fp(x); }
}
int main() {
FP v[3] = { &tiny1, &tiny2, &big };
int s = 0;
for (auto fp : v) s += call(fp, 3);
return s;
}
eof
T=/tmp/Rel/bin
CLANG=$T/clang
"$CLANG" -O2 -flto -fvisibility=hidden -fsanitize=cfi-icall \
-fuse-ld=lld -B"$T" cfi.cc -o cfi -Wl,--lto-emit-asm,--save-temps
sed -i '/\.prefalign/d' cfi.lto.s
cp cfi.lto.s cfi.progbits.s
sed 's|\.text\.\.L\.cfi\.jumptable,"ax", at progbits|.text..L.cfi.jumptable,"ax", at llvm_cfi_jump_table,8|' \
cfi.lto.s > cfi.relax.s
for v in progbits relax; do
"$T"/llvm-mc -filetype=obj -triple=x86_64 cfi.$v.s -o cfi.$v.o
"$CLANG" -fuse-ld=lld -B"$T" cfi.$v.o -o cfi.$v
done
set +e
./cfi.progbits; echo "cfi.progbits exit=$?"
./cfi.relax; echo "cfi.relax exit=$?"
set -e
SYMS=tiny1.cfi,tiny2.cfi,big.cfi,tiny1,tiny2,big
for v in progbits relax; do
printf '\n===== cfi.%s =====\n' "$v"
"$T"/llvm-objdump -d --show-all-symbols --no-show-raw-insn \
--disassemble-symbols=$SYMS cfi.$v
done
printf '\n===== .text size =====\n'
"$T"/llvm-readelf -SW cfi.progbits cfi.relax | \
awk '/^File:/{f=$2} /\.text +PROGBITS/{print f, $6}'
```
https://github.com/llvm/llvm-project/pull/147424
More information about the llvm-branch-commits
mailing list