https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83180
Bug ID: 83180
Summary: MINGW: Linking to libpq.dll produced with MSVC-x64
generates invalid code
Product: gcc
Version: 7.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: l...@greiz-reinsdorf.de
Target Milestone: ---
Created attachment 42731
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=42731&action=edit
Test source code to link to libpq.dll
Hi! I'm a maintainer of the Ruby binding to PostgreSQL. I'm faced with a linker
issue when linking to PQgetvalue() in the libpq.dll for x64 provided by the
PostgreSQL project. The DLL in question is attached. It is part of the official
PostgreSQL download for Windows-x64:
https://get.enterprisedb.com/postgresql/postgresql-10.0-1-windows-x64.exe
The error can be reproduced by using the attached "segfault.c" file like so. It
fails when auto-import is disabled:
$ x86_64-w64-mingw32-gcc -o segfault.exe segfault.c
-IC:/PROGRA~1/POSTGR~1/10/include -LC:/PROGRA~1/POSTGR~1/10/lib
-Wl,--enable-auto-image-base,--disable-auto-import -lpq
C:\Users\kanis\AppData\Local\Temp\cce46Itr.o:segfault.c:(.text+0x11e):
undefined reference to `PQgetvalue'
collect2.exe: error: ld returned 1 exit status
When auto-import is enabled, then linking succeeds, but the generated code is
invalid:
$ x86_64-w64-mingw32-gcc -o segfault.exe segfault.c
-IC:/PROGRA~1/POSTGR~1/10/include -LC:/PROGRA~1/POSTGR~1/10/lib
-Wl,--enable-auto-image-base,--enable-auto-import -lpq
$ objdump -d segfault.exe
[...]
401650: 48 8b 45 f0 mov-0x10(%rbp),%rax
401654: 41 b8 00 00 00 00 mov$0x0,%r8d
40165a: ba 00 00 00 00 mov$0x0,%edx
40165f: 48 89 c1mov%rax,%rcx
401662: e8 d9 17 00 00 callq 402e40
401667: 89 45 ecmov%eax,-0x14(%rbp)
40166a: 8b 45 ecmov-0x14(%rbp),%eax
40166d: 89 c2 mov%eax,%edx
40166f: 48 8d 0d e4 29 00 00lea0x29e4(%rip),%rcx#
40405a <.rdata+0x5a>
401676: e8 25 16 00 00 callq 402ca0
40167b: 48 8b 45 f0 mov-0x10(%rbp),%rax
40167f: 41 b8 00 00 00 00 mov$0x0,%r8d
401685: ba 00 00 00 00 mov$0x0,%edx
40168a: 48 89 c1mov%rax,%rcx
40168d: e8 .byte 0xe8
0040168e <__fu0_PQgetvalue>:
40168e: 66 6d insw (%dx),%es:(%rdi)
401690: 00 00 add%al,(%rax)
401692: 48 89 45 e0 mov%rax,-0x20(%rbp)
401696: 48 8b 45 e0 mov-0x20(%rbp),%rax
40169a: 48 89 c2mov%rax,%rdx
40169d: 48 8d 0d bf 29 00 00lea0x29bf(%rip),%rcx#
404063 <.rdata+0x63>
4016a4: e8 f7 15 00 00 callq 402ca0
[...]
$ ./segfault.exe
conn: 007AA7D0
PQlibVersion: 10
res: 007B7120
len: 3
... The call to PQgetlength() and printf() runs through, but it segfaults on
0x40168d, because the address of callq (opcode 0xe8) is invalid. Obviously the
debug information also doesn't fit to the produced code, so that the opcodes
are not properly decoded.
Other functions like PQgetlength() are not affected. They link fine with
auto-import being enabled or disabled. The only function with this odd behavior
is PQgetvalue().
As a workaround "-l:libpq.lib" can be used to trigger linking to libpq.dll per
MSVC import library. This works for gcc-7.2.0, but older versions of gcc
(4.7.2) fail to link to any function of a MSVC produced libpq.lib file (for
some obviously fixed reason).
The issue doesn't appear when building for 32 bit x86 or when linking to a
libpq.dll produced by MINGW.
The root issue is also reproducible on Appveyor:
https://ci.appveyor.com/project/larskanis/ruby-pg-xa3f5/build/1.0.65/job/b06idaids8el773r
My environment:
$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/lto-wrapper.exe
Target: x86_64-w64-mingw32
Configured with: ../gcc-7.2.0/configure --prefix=/mingw64
--with-local-prefix=/mingw64/local --build=x86_64-w64-mingw32
--host=x86_64-w64-mingw32 --target=x86_64-w64-mingw32
--with-native-system-header-dir=/mingw64/x86_64-w64-mingw32/include
--libexecdir=/mingw64/lib --enable-bootstrap --with-arch=x86-64
--with-tune=generic --enable-languages=c,lto,c++,objc,obj-c++,fortran,ada
--enable-shared --enable-static --enable-libatomic --enable-threads=posix
--enable-graphite --enable-fully-dynamic-string --enable-libstdcxx-time=yes
--disable-libstdcxx-pch --disable-libstdcxx-debug --disable-isl-version-check
--en