[BPF] clang SIGSEGV in CGDebugInfo::EmitFunctionDecl with -g (DILocalVariable::getImpl)
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
### Summary
Clang SIGSEGV (exit code 139) when compiling for the BPF target with `-g` (debug info). The crash occurs in `CGDebugInfo::EmitFunctionDecl` while creating a `DILocalVariable` for an external function declaration's parameter, triggered at the end of the translation unit (`ActOnEndOfTranslationUnit`). Reproduces on clang 19, 21, and 23 trunk — **not fixed** as of clang 23.
This is distinct from #147212, which crashes in the same `EmitFunctionDecl` entry point but in the `CollectRecordFields` → `getASTRecordLayout` subtree (recursive struct layout). The crash here is on the `createParameterVariable` → `DILocalVariable::getImpl` → `MetadataTracking::track` path.
### Reproducer
Preprocessed source (self-contained, no include dependencies; preprocessed with clang 23): https://gist.github.com/choury/b917f18b82e8a2e1d90269be8b68e192
Triggered by compiling a file from OpenSSL 3.0 (`providers/implementations/signature/rsa_sig.c`), but the crash is in clang/LLVM itself, independent of any pass plugin or custom header — `-target bpf -g` alone reproduces it (no `-fpass-plugin=`).
### Compile command
```bash
clang -target bpf -mcpu=v4 -O1 -mllvm -bpf-stack-size=131072 \
-g -Wno-error=int-conversion \
-DL_ENDIAN -U__SIZEOF_INT128__ -DOPENSSL_BUILDING_OPENSSL \
-c rsa_sig.c -o /dev/null
```
Note: `-mllvm -bpf-stack-size=131072` is required to raise the BPF stack limit so the function reaches codegen (without it, a normal "stack limit exceeded" error fires first).
### Stack dump (clang 23 trunk)
```
Stack dump:
0. Program arguments: clang -target bpf -mcpu=v4 -O1 -mllvm -bpf-stack-size=131072 -g ...
1. parser at end of file
#4 llvm::MetadataTracking::track(...) libLLVM-23
#5 llvm::MDNode::MDNode(...) libLLVM-23
#6 llvm::DILocalVariable::getImpl(...) libLLVM-23
#7 llvm::DIBuilder::createParameterVariable(...) libLLVM-23
#8 clang::CodeGen::CGDebugInfo::EmitFunctionDecl(...) libclang-cpp-23
#9 clang::Sema::ActOnEndOfTranslationUnit() libclang-cpp-23
#10 clang::Parser::ParseTopLevelDecl(...)
clang: error: clang frontend command failed with exit code 139
```
### Key observations
1. **`-g` is the trigger.** Without `-g` (or with `-debug-info-kind=none`), the same file compiles (or fails with a normal, unrelated BPF SelectionDAG error). Tested with `-debug-info-kind=limited|standalone|line-tables-only` → all crash; `none` → OK.
2. **`-target bpf` is required.** The same file with `--target=x86_64-linux-gnu -g` compiles cleanly. BPF-specific.
3. **No pass plugin involved.** Reproduces with stock clang, no `-fpass-plugin=`.
4. **Deterministic, not a race.** The same file crashes 100% across repeated runs. It only *appears* sporadic in a parallel build because only a fraction of source files contain the triggering external declaration shape.
### Version matrix
Same reproducer (`rsa_sig.c`, preprocessed with clang 23), all three crash in the **identical** `EmitFunctionDecl → DILocalVariable::getImpl` stack frame:
| clang version | result |
|---|---|
| **19.1.7** (Debian) | **SIGSEGV** (exit 139) |
| **21.1.8** | **SIGSEGV** (exit 139) |
| **23 trunk** `cd3bfc1f9926` (2026-06-22) | **SIGSEGV** (exit 139) |
So the bug is **not fixed** on clang 23 trunk. (One earlier reproducer file from the same tree, `encoder_lib.c`, happened to stop crashing on 21/23 — but that was incidental, its triggering declaration shape apparently shifted; `rsa_sig.c` crashes consistently across all three versions.)
### Workaround
Drop `-g` (and the dependent `-fstack-size-section`) when compiling BPF code that triggers this. The bug is still present on trunk (clang 23) as of 2026-06-22.
Contributor guide
Research direction
Run the supplied clang command against the linked preprocessed reproducer and confirm the SIGSEGV in the EmitFunctionDecl → createParameterVariable → DILocalVariable::getImpl path. Then read the compiler and debug-info code around CGDebugInfo::EmitFunctionDecl and reproduce across the listed debug-info modes and targets. Done means the BPF reproducer no longer crashes with -g while the existing non-crash behavior remains intact.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100