GDB compiled with
x86_64-w64-mingw32-gcc (GCC) 4.5.0 20090726 (experimental)
doesn't work (refuses to load symbols for any executable).
This is happening because is_regular_file in gdb/source.c appears to be
mis-optimized (disabling optimization for that one file produces a working
GDB).
The source reads:
/* Return True if the file NAME exists and is a regular file */
static int
is_regular_file (const char *name)
{
struct stat st;
const int status = stat (name, &st);
/* Stat should never fail except when the file does not exist.
If stat fails, analyze the source of error and return True
unless the file does not exist, to avoid returning false results
on obscure systems where stat does not work as expected.
*/
if (status != 0)
return (errno != ENOENT);
return S_ISREG (st.st_mode);
}
Oprimized code is:
00000000000005d0 <_is_regular_file>:
5d0: 48 81 ec 98 00 00 00 sub $0x98,%rsp
5d7: 48 8d 54 24 20 lea 0x20(%rsp),%rdx
5dc: ff 15 00 00 00 00 callq *0x0(%rip) # 5e2
<_is_regular_file+0x12>
5de: R_X86_64_PC32 __imp___stat64
5e2: 85 c0 test %eax,%eax
5e4: 75 1d jne 603 <_is_regular_file+0x33>
5e6: 0f b7 44 24 66 movzwl 0x66(%rsp),%eax
5eb: 25 00 f0 00 00 and $0xf000,%eax
5f0: 3d 00 80 00 00 cmp $0x8000,%eax
5f5: 0f 94 c0 sete %al
5f8: 48 81 c4 98 00 00 00 add $0x98,%rsp
5ff: 0f b6 c0 movzbl %al,%eax
602: c3 retq
603: ff 15 00 00 00 00 callq *0x0(%rip) # 609
<_is_regular_file+0x39>
605: R_X86_64_PC32 __imp___errno
609: 83 38 02 cmpl $0x2,(%rax)
60c: 0f 95 c0 setne %al
60f: 48 81 c4 98 00 00 00 add $0x98,%rsp
616: 0f b6 c0 movzbl %al,%eax
619: c3 retq
Without optimization:
0000000000000e89 <_is_regular_file>:
e89: 55 push %rbp
e8a: 48 89 e5 mov %rsp,%rbp
e8d: 48 83 ec 60 sub $0x60,%rsp
e91: 48 89 4d 10 mov %rcx,0x10(%rbp)
e95: 48 8d 45 c0 lea -0x40(%rbp),%rax
e99: 48 89 c2 mov %rax,%rdx
e9c: 48 8b 4d 10 mov 0x10(%rbp),%rcx
ea0: e8 00 00 00 00 callq ea5 <_is_regular_file+0x1c>
ea1: R_X86_64_PC32 _stat
ea5: 89 45 fc mov %eax,-0x4(%rbp)
ea8: 83 7d fc 00 cmpl $0x0,-0x4(%rbp)
eac: 74 16 je ec4 <_is_regular_file+0x3b>
eae: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax # eb5
<_is_regular_file+0x2c>
eb1: R_X86_64_PC32 __imp___errno
eb5: ff d0 callq *%rax
eb7: 8b 00 mov (%rax),%eax
eb9: 83 f8 02 cmp $0x2,%eax
ebc: 0f 95 c0 setne %al
ebf: 0f b6 c0 movzbl %al,%eax
ec2: eb 17 jmp edb <_is_regular_file+0x52>
ec4: 0f b7 45 c6 movzwl -0x3a(%rbp),%eax
ec8: 0f b7 c0 movzwl %ax,%eax
ecb: 25 00 f0 00 00 and $0xf000,%eax
ed0: 3d 00 80 00 00 cmp $0x8000,%eax
ed5: 0f 94 c0 sete %al
ed8: 0f b6 c0 movzbl %al,%eax
edb: c9 leaveq
edc: c3 retq
It appears that unoptimized code calls _stat, which jumps to _stat64i32, which
has this:
extern __inline__ int __attribute__((__cdecl__)) _stat64i32(const char
*_Name,struct _stat64i32 *_Stat)
{
struct _stat64 st;
int ret=_stat64(_Name,&st); // calls _imp___stat64
_Stat->st_dev=st.st_dev;
_Stat->st_ino=st.st_ino;
_Stat->st_mode=st.st_mode;
_Stat->st_nlink=st.st_nlink;
_Stat->st_uid=st.st_uid;
_Stat->st_gid=st.st_gid;
_Stat->st_rdev=st.st_rdev;
_Stat->st_size=(_off_t) st.st_size;
_Stat->st_atime=st.st_atime;
_Stat->st_mtime=st.st_mtime;
_Stat->st_ctime=st.st_ctime;
return ret;
}
whereas the optimized code calls into _imp__stat64 directly and doesn't perform
the _stat64 -> _stat64i32 transformation.
In the optimized case, immediately after _imp___stat64 returns:
(gdb) p/x st
$1 = {st_dev = 0x22a520, st_ino = 0x0, st_mode = 0x0, st_nlink = 0x4,
st_uid = 0x0, st_gid = 0x0, st_rdev = 0x68a4e5, st_size = 0x0,
st_atime = 0x7ff7fc35af9, st_mtime = 0x0, st_ctime = 0x1}
In the non-optimized case, immediately after _stat returns:
(gdb) p/x st
$1 = {st_dev = 0x2, st_ino = 0x0, st_mode = 0x81ff, st_nlink = 0x1,
st_uid = 0x0, st_gid = 0x0, st_rdev = 0x2, st_size = 0x12c9aa9,
st_atime = 0x4a713f85, st_mtime = 0x4a713f85, st_ctime = 0x4a713f83}
--- reproduces with t.c ---
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(int argc, char *argv[])
{
struct stat st;
if (0 == stat(argv[0], &st))
printf("mode = %x\n", st.st_mode);
return 0;
}
--- t.c ---
/usr/local/mingw-w64/bin/x86_64-w64-mingw32-gcc -g t.c -O2 && ./a.exe
mode = 0
/usr/local/mingw-w64/bin/x86_64-w64-mingw32-gcc -g t.c -O0 && ./a.exe
mode = 81ff
--
Summary: GCC mis-optimizes GDB
Product: gcc
Version: 4.5.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: ppluzhnikov at google dot com
GCC build triplet: i686-pc-cygwin
GCC host triplet: x86_64-w64-mingw32
GCC target triplet: x86_64-w64-mingw32
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40909