llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.63k stars 11.83k forks source link

[Win64] EHcont just doesn't seem work with SEH #64585

Open namazso opened 1 year ago

namazso commented 1 year ago

Reproducer:

#include <cstdio>

[[gnu::noinline]] void exception() {
    *(char*)1 = 0;
}

__asm__(R"(
.text
.balign 16
.globl test_seh
.def test_seh; .scl 2; .type 32; .endef
.seh_proc test_seh
test_seh:
  .seh_handler __C_specific_handler, @except
  .seh_handlerdata
  .long 1
  .long (seh_begin)@IMGREL
  .long (seh_end)@IMGREL
  .long 1
  .long (seh_except)@IMGREL
  .text
seh_begin:
  nop
  int3
  nop
seh_end:
seh_except:
  ret
.seh_endproc

.section .gehcont$y,"dr"
.symidx seh_except
)");

extern "C" void test_seh();

int main() {
    test_seh();
    printf("Test from assembly worked!\n");
    __try {
        exception();
    } __except(1) {
    }
    printf("Test from C worked!\n");
    return 0;
}

Output (link.exe is used for linking due to LLD bug with EHcont):

> clang-cl --version
clang version 16.0.6
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: C:\Program Files\LLVM\bin

> clang-cl /guard:ehcont -fuse-ld=link test.cpp /link /guard:cf,ehcont

>.\test.exe
Test from assembly worked!

> echo %ERRORLEVEL%
-1073740791

I'll investigate a bit more to find out where the issue could be, as this functionality is supposedly tested by https://github.com/llvm/llvm-project/blob/345acac85d382998e5721073cc077e47e799311f/llvm/test/CodeGen/X86/ehcontguard.ll

namazso commented 1 year ago

I found part of the issue:

This condition triggers, resulting in an early return:

https://github.com/llvm/llvm-project/blob/main/llvm/lib/CodeGen/AsmPrinter/WinException.cpp#L136-L137

Which results in this piece of code not running:

https://github.com/llvm/llvm-project/blob/main/llvm/lib/CodeGen/AsmPrinter/WinException.cpp#L163-L166

Adding a dirty goto in place of the return makes it emit the section at least.

namazso commented 1 year ago

Unfortunately this isn't a fix yet as the symbol points at the wrong place:

image