Crash when accessing UnsafeMutablePointer with “-Xlinker -debug” flags

What happened?

Accessing UnsafeMutablePointer and other pointers with Swift's -Xlinker -debug enabled raises an Exception

Environment

S:\src\swift-issue-windows\hand>swift --version
compnerd.org Swift version 6.0-dev (LLVM 1a1e1e53e130e97, Swift b93c0be01b9d7dd)
Target: x86_64-unknown-windows-msvc

CMakeLists.txt

project(hello LANGUAGES Swift)

add_link_options(
  "-Xlinker" "-debug"
)

add_executable(hello hello.swift)

Hello.swift

let allocatePtr = UnsafeMutablePointer<Int>.allocate(capacity: 1)
allocatePtr.initialize(to: 42)
let s = allocatePtr.pointee + 1
print(s) // throw Exception

using command

mkdir build
cd build
cmake -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo ..
cmake --build .
lldb hello.exe

output log

* thread #1, stop reason = Exception 0xc0000005 encountered at address 0x7ffd901ad8e4: Access violation reading location 0x7ff6d62bfc19
    frame #0: 0x00007ffd901ad8e4 swiftCore.dll`swift_conformsToProtocol + 5556
swiftCore.dll`swift_conformsToProtocol:
->  0x7ffd901ad8e4 <+5556>: movq   (%rax), %rax
    0x7ffd901ad8e7 <+5559>: jmp    0x7ffd901ad8eb ; <+5563>
    0x7ffd901ad8e9 <+5561>: xorl   %eax, %eax
    0x7ffd901ad8eb <+5563>: movq   (%rsi), %rcx

On Windows, “app.pdb” can be generated by using “-Xlinker -debug” flags. By explicitly setting this option in CMakeLists.txt, I can debug with WinDbg and LLDB. Is this a bug in Swift or lld-link.exe? Or is there an error in my code?

Are you always doing a clean build and hitting this? If there is an incremental build, this would be a problem. This is something that LLD does not support and thus if you are linking with lld, it should work fine (-use-ld=lld). The padding for incremental linking causes issues for the runtime initialisation.

1 Like

thanks @compnerd -san.

The reason for my mistake was that I had assumed LLD would be used even without specifying -use-ld. In reality, for static linking, if nothing is specified, 'link' is used as is. I understood this by reading WindowsToolChains.cpp. By specifying the -use-ld=lld option that you suggested, it worked correctly.

The padding for incremental linking causes issues for the runtime initialisation.

I understand why this was failing as an "Access violation reading location 0xAddress". Thank you for explaining it to me.

link.exe is the platform linker and is preferred (just as ld64 is the preferred platform linker on Darwin).

For SPM, we default to lld by means of an external configuration file (Info.plist) which specifies SWIFTC_FLAGS which is used as the default set of flags to pass the compiler. Included in this is -use-ld=lld. For CMake, no such override is considered which is why you need to specify it.

1 Like