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

Reply via email to