Issue |
148170
|
Summary |
clang >= 18 .cfi frame check rejects assembly generated by clang (Mach-O)
|
Labels |
clang
|
Assignees |
|
Reporter |
sternenseemann
|
## Background
When upgrading clang in Nixpkgs, older versions of GHC started hitting the [cfi frame check](https://github.com/llvm/llvm-project/commit/d506aa4edfa66074db3dc1fa84da9d9c80d71500) for darwin introduced in clang 18. This happens while compiling the file [rts/StgCRun.c](https://gitlab.haskell.org/ghc/ghc/-/blob/ghc-9.12.2-release/rts/StgCRun.c?ref_type=tags) which has a bunch of inline assembly which notably contains labels, but no `.cfi_startproc`/`endproc`.
While this only affected GHC versions before 9.6, the `StgCRun.c` wasn't changed in any meaningful way to alleviate the issue. I eventually figured out that GHC used to (before 9.6) roundtrip C compilation via assembly, i.e. it would run `clang -S` followed by `clang -c` using the generated assembly file as an input. This [was changed](https://gitlab.haskell.org/ghc/ghc/-/merge_requests/6877) for 9.6 (mainly to benefit wasm compilation).
## The (potential) bug
I concluded that, for Mach-O, `clang -c` will, without complains, translate one and the same C file to object code directly that it would reject (due to the cfi frame check) if it is translated to assembly first (by the same version of clang). This is shown by the reproducer below.
I'm not sure if this should be considered a bug or not. `StgCRun.c` is definitely not bog standard C and I'm not sure whether `clang` can figure that the translation is safe in the context of the C file, but not in the case of the no context assembly file.
Unless other software is also affected by this, it is not worth fixing this for the sake of some GHC versions that should go out of use soon (hopefully). I'm mostly reporting this in case LLVM considers this inconsistency a bug that should be fixed.
## Reproducer
The issue can relatively easily be reproduced using the following commands on a Darwin machine. I didn't test clang 18 and 20, but they should also exhibit the same issue. I'm happy to test any specific clang version, e.g. `main`, if required, just let me know.
```console
$ curl https://downloads.haskell.org/ghc/9.12.2/ghc-9.12.2-src.tar.gz | tar -zxv
$ cd ghc-*/rts/
$ clang --version
clang version 19.1.7
Target: arm64-apple-darwin
Thread model: posix
InstalledDir: /nix/store/702wr5c2h7z8r6nhl7sjrw5d0af9xbdv-clang-19.1.7/bin
$ ./configure
(I think this should succeed if Developer Tools or similar installed, let me know if it gives you any trouble.)
$ clang -S -o StgCRun.asm StgCRun.c -I include -I .
$ clang -c -o StgCRun.o StgCRun.asm -I include -I .
StgCRun.asm:46:1: error: non-private labels cannot appear between .cfi_startproc / .cfi_endproc pairs
StgReturn:
^
StgCRun.asm:7:2: error: previous .cfi_startproc was here
.cfi_startproc
^
$ rm -f StgCRun.asm StgCRun.o
$ clang -c -o StgCRun.o StgCRun.c -I include -I .
$ ls *.o
StgCRun.o
```
## See also
- [Original Nixpkgs Issue](https://github.com/NixOS/nixpkgs/issues/367686)
- [GHC Ticket](https://gitlab.haskell.org/ghc/ghc/-/issues/25608). Unfortunately the affected GHC versions are no longer maintained, so this won't be addressed.
- [GHC MR removing the roundtrip via Assembly, fixing the issue](https://gitlab.haskell.org/ghc/ghc/-/merge_requests/6877)
- [Partial backport of this MR's changes to GHC 9.4, fixing the issue](https://github.com/NixOS/nixpkgs/pull/410085). This is unfortunately nontrivial for GHC < 9.4 due to extensive refactors.
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs