[PATCH 0/7] Add "Windows" OS ABI

classic Classic list List threaded Threaded
39 messages Options
12
Reply | Threaded
Open this post in threaded view
|

[PATCH 0/7] Add "Windows" OS ABI

Sourceware - gdb-patches mailing list
This patchset started out as a single patch to have the OS ABI Cygwin
applied to Windows x86-64 binaries, here:

    https://sourceware.org/legacy-ml/gdb-patches/2020-03/msg00195.html

with the follow-up here:

    https://sourceware.org/pipermail/gdb-patches/2020-March/000022.html

Eli pointed out that it doesn't make sense for binaries compilied with
MinGW to have the Cygwin OS ABI, that there should be separate OS ABIs
for Cygwin and non-Cygwin Windows binaries.  This already came up in the
following bug report:

    https://sourceware.org/bugzilla/show_bug.cgi?id=21500#add_comment

This patchset does a bit of refactor in that area.  Most importantly, it:

- adds a "Windows" OS ABI
- makes GDB recognize the proper OS ABI (Cygwin or Windows) when
  loading executables
- makes the builtin long type on Cygwin be 64 bits long

Simon Marchi (7):
  gdb: recognize 64 bits Windows executables as Cygwin osabi
  gdb: move enum gdb_osabi to osabi.h
  gdb: add Windows OS ABI
  gdb: rename i386-cygwin-tdep.c to i386-windows-tdep.c
  gdb: rename content of i386-windows-tdep.c, cygwin to windows
  gdb: select "Cygwin" OS ABI for Cygwin binaries
  gdb: define builtin long type to be 64 bits on amd64 Cygwin

 gdb/Makefile.in                               |   4 +-
 gdb/amd64-windows-tdep.c                      |  41 ++++++-
 gdb/configure.tgt                             |  10 +-
 gdb/defs.h                                    |  31 ------
 gdb/gdbarch.h                                 |   1 +
 gdb/gdbarch.sh                                |   1 +
 ...i386-cygwin-tdep.c => i386-windows-tdep.c} |  45 +++++---
 gdb/osabi.c                                   |   1 +
 gdb/osabi.h                                   |  32 ++++++
 gdb/windows-tdep.c                            | 101 ++++++++++++++++++
 gdb/windows-tdep.h                            |   6 ++
 11 files changed, 215 insertions(+), 58 deletions(-)
 rename gdb/{i386-cygwin-tdep.c => i386-windows-tdep.c} (83%)

--
2.25.1

Reply | Threaded
Open this post in threaded view
|

[PATCH 1/7] gdb: recognize 64 bits Windows executables as Cygwin osabi

Sourceware - gdb-patches mailing list
From: Simon Marchi <[hidden email]>

If I generate two Windows PE executables, one 32 bits and one 64 bits:

    $ x86_64-w64-mingw32-gcc test.c -g3 -O0 -o test_64
    $ i686-w64-mingw32-gcc test.c -g3 -O0 -o test_32
    $ file test_64
    test_64: PE32+ executable (console) x86-64, for MS Windows
    $ file test_32
    test_32: PE32 executable (console) Intel 80386, for MS Windows

When I load the 32 bits binary in my GNU/Linux-hosted GDB, the osabi is
correctly recognized as "Cygwin":

    $ ./gdb --data-directory=data-directory -nx test_32
    (gdb) show osabi
    The current OS ABI is "auto" (currently "Cygwin").

When I load the 64 bits binary in GDB, the osabi is incorrectly
recognized as "GNU/Linux":

    $ ./gdb --data-directory=data-directory -nx test_64
    (gdb) show osabi
    The current OS ABI is "auto" (currently "GNU/Linux").

The 32 bits one gets recognized by the i386_cygwin_osabi_sniffer
function, by its target name:

    if (strcmp (target_name, "pei-i386") == 0)
      return GDB_OSABI_CYGWIN;

The target name for the 64 bits binaries is "pei-x86-64".  It doesn't
get recognized by any osabi sniffer, so GDB falls back on its default
osabi, "GNU/Linux".

This patch adds an osabi sniffer function for the Windows 64 bits
executables in amd64-windows-tdep.c.  With it, the osabi is recognized
as "Cygwin", just like with the 32 bits binary.

Note that it may seems strange to have a binary generated by MinGW
(which has nothing to do with Cygwin) be recognized as a Cygwin binary.
This is indeed not accurate, but at the moment GDB uses the Cygwin for
everything Windows.  Subsequent patches will add a separate "Windows" OS
ABI for Windows binaries that are not Cygwin binaries.

gdb/ChangeLog:

        * amd64-windows-tdep.c (amd64_windows_osabi_sniffer): New
        function.
        (_initialize_amd64_windows_tdep): Register osabi sniffer.
---
 gdb/amd64-windows-tdep.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/gdb/amd64-windows-tdep.c b/gdb/amd64-windows-tdep.c
index d4d79682dd18..2ca979513cd7 100644
--- a/gdb/amd64-windows-tdep.c
+++ b/gdb/amd64-windows-tdep.c
@@ -1244,10 +1244,24 @@ amd64_windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_gdbarch_auto_wide_charset (gdbarch, amd64_windows_auto_wide_charset);
 }
 
+static gdb_osabi
+amd64_windows_osabi_sniffer (bfd *abfd)
+{
+  const char *target_name = bfd_get_target (abfd);
+
+  if (strcmp (target_name, "pei-x86-64") == 0)
+    return GDB_OSABI_CYGWIN;
+
+  return GDB_OSABI_UNKNOWN;
+}
+
 void _initialize_amd64_windows_tdep ();
 void
 _initialize_amd64_windows_tdep ()
 {
   gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, GDB_OSABI_CYGWIN,
                           amd64_windows_init_abi);
+
+  gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
+  amd64_windows_osabi_sniffer);
 }
--
2.25.1

Reply | Threaded
Open this post in threaded view
|

[PATCH 2/7] gdb: move enum gdb_osabi to osabi.h

Sourceware - gdb-patches mailing list
In reply to this post by Sourceware - gdb-patches mailing list
From: Simon Marchi <[hidden email]>

I think it makes sense to have it there instead of in the catch-all
defs.h.

gdb/ChangeLog:

        * defs.h (enum gdb_osabi): Move to...
        * osabi.h (enum gdb_osabi): ... here.
        * gdbarch.sh: Include osabi.h in gdbarch.h.
        * gdbarch.h: Re-generate.
---
 gdb/defs.h     | 31 -------------------------------
 gdb/gdbarch.h  |  1 +
 gdb/gdbarch.sh |  1 +
 gdb/osabi.h    | 31 +++++++++++++++++++++++++++++++
 4 files changed, 33 insertions(+), 31 deletions(-)

diff --git a/gdb/defs.h b/gdb/defs.h
index 1ad52feb1f80..a75511158a40 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -478,37 +478,6 @@ enum val_prettyformat
 
 extern int longest_to_int (LONGEST);
 
-/* * List of known OS ABIs.  If you change this, make sure to update the
-   table in osabi.c.  */
-enum gdb_osabi
-{
-  GDB_OSABI_UNKNOWN = 0, /* keep this zero */
-  GDB_OSABI_NONE,
-
-  GDB_OSABI_SVR4,
-  GDB_OSABI_HURD,
-  GDB_OSABI_SOLARIS,
-  GDB_OSABI_LINUX,
-  GDB_OSABI_FREEBSD,
-  GDB_OSABI_NETBSD,
-  GDB_OSABI_OPENBSD,
-  GDB_OSABI_WINCE,
-  GDB_OSABI_GO32,
-  GDB_OSABI_QNXNTO,
-  GDB_OSABI_CYGWIN,
-  GDB_OSABI_AIX,
-  GDB_OSABI_DICOS,
-  GDB_OSABI_DARWIN,
-  GDB_OSABI_SYMBIAN,
-  GDB_OSABI_OPENVMS,
-  GDB_OSABI_LYNXOS178,
-  GDB_OSABI_NEWLIB,
-  GDB_OSABI_SDE,
-  GDB_OSABI_PIKEOS,
-
-  GDB_OSABI_INVALID /* keep this last */
-};
-
 /* Enumerate the requirements a symbol has in order to be evaluated.
    These are listed in order of "strength" -- a later entry subsumes
    earlier ones.  This fine-grained distinction is important because
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 0259fcdbfd26..6dbb9d571ddb 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -40,6 +40,7 @@
 #include "dis-asm.h"
 #include "gdb_obstack.h"
 #include "infrun.h"
+#include "osabi.h"
 
 struct floatformat;
 struct ui_file;
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index 4a4b1bc66cfa..5a39dec83da2 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -1313,6 +1313,7 @@ cat <<EOF
 #include "dis-asm.h"
 #include "gdb_obstack.h"
 #include "infrun.h"
+#include "osabi.h"
 
 struct floatformat;
 struct ui_file;
diff --git a/gdb/osabi.h b/gdb/osabi.h
index bb0812e567f4..ff63db49affe 100644
--- a/gdb/osabi.h
+++ b/gdb/osabi.h
@@ -19,6 +19,37 @@
 #ifndef OSABI_H
 #define OSABI_H
 
+/* * List of known OS ABIs.  If you change this, make sure to update the
+   table in osabi.c.  */
+enum gdb_osabi
+{
+  GDB_OSABI_UNKNOWN = 0, /* keep this zero */
+  GDB_OSABI_NONE,
+
+  GDB_OSABI_SVR4,
+  GDB_OSABI_HURD,
+  GDB_OSABI_SOLARIS,
+  GDB_OSABI_LINUX,
+  GDB_OSABI_FREEBSD,
+  GDB_OSABI_NETBSD,
+  GDB_OSABI_OPENBSD,
+  GDB_OSABI_WINCE,
+  GDB_OSABI_GO32,
+  GDB_OSABI_QNXNTO,
+  GDB_OSABI_CYGWIN,
+  GDB_OSABI_AIX,
+  GDB_OSABI_DICOS,
+  GDB_OSABI_DARWIN,
+  GDB_OSABI_SYMBIAN,
+  GDB_OSABI_OPENVMS,
+  GDB_OSABI_LYNXOS178,
+  GDB_OSABI_NEWLIB,
+  GDB_OSABI_SDE,
+  GDB_OSABI_PIKEOS,
+
+  GDB_OSABI_INVALID /* keep this last */
+};
+
 /* Register an OS ABI sniffer.  Each arch/flavour may have more than
    one sniffer.  This is used to e.g. differentiate one OS's a.out from
    another.  The first sniffer to return something other than
--
2.25.1

Reply | Threaded
Open this post in threaded view
|

[PATCH 3/7] gdb: add Windows OS ABI

Sourceware - gdb-patches mailing list
In reply to this post by Sourceware - gdb-patches mailing list
From: Simon Marchi <[hidden email]>

GDB currently uses the "Cygwin" OS ABI (GDB_OSABI_CYGWIN) for everything
related to Windows.  If you build a GDB for a MinGW or Cygwin target, it
will have "Cygwin" as the default OS ABI in both cases (see
configure.tgt).  If you load either a MinGW or Cygwin binary, the
"Cygwin" OS ABI will be selected in both cases.

This is misleading, because Cygwin binaries are a subset of the binaries
running on Windows.  When building something with MinGW, the resulting
binary has nothing to do with Cygwin.  Cygwin binaries are only special
in that they are Windows binaries that link to the cygwin1.dll library
(if my understanding is correct).

Looking at i386-cygwin-tdep.c, we can see that GDB does nothing
different when dealing with Cygwin binaries versus non-Cygwin Windows
binaries.  However, there is at least one known bug which would require
us to make a distinction between the two OS ABIs, and that is the size
of the built-in "long" type on x86-64.  On native Windows, this is 4,
whereas on Cygwin it's 8.

So, this patch adds a new OS ABI, "Windows", and makes GDB use it for
i386 and x86-64 PE executables, instead of the "Cygwin" OS ABI.  A
subsequent patch will improve the OS ABI detection so that GDB
differentiates the non-Cygwin Windows binaries from the Cygwin Windows
binaries, and applies the "Cygwin" OS ABI for the latter.

The default OS ABI remains "Cygwin" for the GDBs built with a Cygwin
target.

I've decided to split the i386_cygwin_osabi_sniffer function in two,
I think it's cleaner to have a separate sniffer for Windows binaries and
Cygwin cores, each checking one specific thing.

gdb/ChangeLog:

        * osabi.h (enum gdb_osabi): Add GDB_OSABI_WINDOWS.
        * osabi.c (gdb_osabi_names): Add "Windows".
        * i386-cygwin-tdep.c (i386_cygwin_osabi_sniffer): Return
        GDB_OSABI_WINDOWS when the binary's target is "pei-i386".
        (i386_cygwin_core_osabi_sniffer): New function, extracted from
        i386_cygwin_osabi_sniffer.
        (_initialize_i386_cygwin_tdep): Register OS ABI
        GDB_OSABI_WINDOWS for i386.
        * amd64-windows-tdep.c (amd64_windows_osabi_sniffer): Return
        GDB_OSABI_WINDOWS when the binary's target is "pei-x86-64".
        (_initialize_amd64_windows_tdep): Register OS ABI GDB_OSABI_WINDOWS
        for x86-64.
        * configure.tgt: Use GDB_OSABI_WINDOWS as the default OS ABI
        when the target matches '*-*-mingw*'.
---
 gdb/amd64-windows-tdep.c |  5 ++++-
 gdb/configure.tgt        |  4 ++--
 gdb/i386-cygwin-tdep.c   | 17 ++++++++++++++---
 gdb/osabi.c              |  1 +
 gdb/osabi.h              |  1 +
 5 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/gdb/amd64-windows-tdep.c b/gdb/amd64-windows-tdep.c
index 2ca979513cd7..88ff794abcb6 100644
--- a/gdb/amd64-windows-tdep.c
+++ b/gdb/amd64-windows-tdep.c
@@ -1250,7 +1250,7 @@ amd64_windows_osabi_sniffer (bfd *abfd)
   const char *target_name = bfd_get_target (abfd);
 
   if (strcmp (target_name, "pei-x86-64") == 0)
-    return GDB_OSABI_CYGWIN;
+    return GDB_OSABI_WINDOWS;
 
   return GDB_OSABI_UNKNOWN;
 }
@@ -1259,6 +1259,9 @@ void _initialize_amd64_windows_tdep ();
 void
 _initialize_amd64_windows_tdep ()
 {
+  /* The Cygwin and Windows OS ABIs are currently equivalent.  */
+  gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, GDB_OSABI_WINDOWS,
+                          amd64_windows_init_abi);
   gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, GDB_OSABI_CYGWIN,
                           amd64_windows_init_abi);
 
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index 755187dca657..6ebd32410e99 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -771,8 +771,8 @@ m68*-*-openbsd* | m88*-*-openbsd* | vax-*-openbsd*) ;;
 *-*-*-gnu*) ;; # prevent non-GNU kernels to match the Hurd rule below
 *-*-gnu*) gdb_osabi=GDB_OSABI_HURD ;;
 *-*-mingw32ce*) gdb_osabi=GDB_OSABI_WINCE ;;
-*-*-mingw* | *-*-cygwin*)
- gdb_osabi=GDB_OSABI_CYGWIN ;;
+*-*-mingw*) gdb_osabi=GDB_OSABI_WINDOWS ;;
+*-*-cygwin*) gdb_osabi=GDB_OSABI_CYGWIN ;;
 *-*-dicos*) gdb_osabi=GDB_OSABI_DICOS ;;
 *-*-symbianelf*)
  gdb_osabi=GDB_OSABI_SYMBIAN ;;
diff --git a/gdb/i386-cygwin-tdep.c b/gdb/i386-cygwin-tdep.c
index cb66632648f7..b9a959d3c7d4 100644
--- a/gdb/i386-cygwin-tdep.c
+++ b/gdb/i386-cygwin-tdep.c
@@ -232,14 +232,22 @@ i386_cygwin_osabi_sniffer (bfd *abfd)
   const char *target_name = bfd_get_target (abfd);
 
   if (strcmp (target_name, "pei-i386") == 0)
-    return GDB_OSABI_CYGWIN;
+    return GDB_OSABI_WINDOWS;
+
+  return GDB_OSABI_UNKNOWN;
+}
+
+static enum gdb_osabi
+i386_cygwin_core_osabi_sniffer (bfd *abfd)
+{
+  const char *target_name = bfd_get_target (abfd);
 
   /* Cygwin uses elf core dumps.  Do not claim all ELF executables,
      check whether there is a .reg section of proper size.  */
   if (strcmp (target_name, "elf32-i386") == 0)
     {
       asection *section = bfd_get_section_by_name (abfd, ".reg");
-      if (section
+      if (section != nullptr
   && bfd_section_size (section) == I386_WINDOWS_SIZEOF_GREGSET)
  return GDB_OSABI_CYGWIN;
     }
@@ -256,8 +264,11 @@ _initialize_i386_cygwin_tdep ()
 
   /* Cygwin uses elf core dumps.  */
   gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour,
-                                  i386_cygwin_osabi_sniffer);
+                                  i386_cygwin_core_osabi_sniffer);
 
+  /* The Cygwin and Windows OS ABIs are currently equivalent.  */
   gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_CYGWIN,
                           i386_cygwin_init_abi);
+  gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_WINDOWS,
+                          i386_cygwin_init_abi);
 }
diff --git a/gdb/osabi.c b/gdb/osabi.c
index b9a8687a7cc3..627b9d981515 100644
--- a/gdb/osabi.c
+++ b/gdb/osabi.c
@@ -72,6 +72,7 @@ static const struct osabi_names gdb_osabi_names[] =
   { "DJGPP", NULL },
   { "QNX-Neutrino", NULL },
   { "Cygwin", NULL },
+  { "Windows", NULL },
   { "AIX", NULL },
   { "DICOS", NULL },
   { "Darwin", NULL },
diff --git a/gdb/osabi.h b/gdb/osabi.h
index ff63db49affe..a7e6a10d0198 100644
--- a/gdb/osabi.h
+++ b/gdb/osabi.h
@@ -37,6 +37,7 @@ enum gdb_osabi
   GDB_OSABI_GO32,
   GDB_OSABI_QNXNTO,
   GDB_OSABI_CYGWIN,
+  GDB_OSABI_WINDOWS,
   GDB_OSABI_AIX,
   GDB_OSABI_DICOS,
   GDB_OSABI_DARWIN,
--
2.25.1

Reply | Threaded
Open this post in threaded view
|

[PATCH 4/7] gdb: rename i386-cygwin-tdep.c to i386-windows-tdep.c

Sourceware - gdb-patches mailing list
In reply to this post by Sourceware - gdb-patches mailing list
From: Simon Marchi <[hidden email]>

Since this file contains things that apply not only to Cygwin binaries,
but also to non-Cygwin Windows binaries, I think it would make more
sense for it to be called i386-windows-tdep.c.  It is analogous to
amd64-windows-tdep.c, which we already have.

gdb/ChangeLog:

        * i386-cygwin-tdep.c: Rename to...
        * i386-windows-tdep.c: ... this.
        * Makefile.in (ALL_TARGET_OBS): Rename i386-cygwin-tdep.c to
        i386-windows-tdep.c.
        * configure.tgt: Likewise.
---
 gdb/Makefile.in                                 | 4 ++--
 gdb/configure.tgt                               | 6 +++---
 gdb/{i386-cygwin-tdep.c => i386-windows-tdep.c} | 0
 3 files changed, 5 insertions(+), 5 deletions(-)
 rename gdb/{i386-cygwin-tdep.c => i386-windows-tdep.c} (100%)

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 1db02c07ac28..d225b7d76679 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -733,7 +733,6 @@ ALL_TARGET_OBS = \
  hppa-obsd-tdep.o \
  hppa-tdep.o \
  i386-bsd-tdep.o \
- i386-cygwin-tdep.o \
  i386-darwin-tdep.o \
  i386-dicos-tdep.o \
  i386-fbsd-tdep.o \
@@ -745,6 +744,7 @@ ALL_TARGET_OBS = \
  i386-obsd-tdep.o \
  i386-sol2-tdep.o \
  i386-tdep.o \
+ i386-windows-tdep.o \
  i387-tdep.o \
  iq2000-tdep.o \
  linux-record.o \
@@ -2161,7 +2161,6 @@ ALLDEPFILES = \
  hppa-tdep.c \
  i386-bsd-nat.c \
  i386-bsd-tdep.c \
- i386-cygwin-tdep.c \
  i386-darwin-nat.c \
  i386-darwin-tdep.c \
  i386-dicos-tdep.c \
@@ -2178,6 +2177,7 @@ ALLDEPFILES = \
  i386-sol2-nat.c \
  i386-sol2-tdep.c \
  i386-tdep.c \
+ i386-windows-tdep.c \
  i387-tdep.c \
  ia64-libunwind-tdep.c \
  ia64-linux-nat.c \
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index 6ebd32410e99..34f703009eaa 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -304,11 +304,11 @@ i[34567]86-*-gnu*)
  ;;
 i[34567]86-*-cygwin*)
  # Target: Intel 386 running win32
- gdb_target_obs="i386-cygwin-tdep.o windows-tdep.o"
+ gdb_target_obs="i386-windows-tdep.o windows-tdep.o"
  ;;
 i[34567]86-*-mingw32*)
  # Target: Intel 386 running win32
- gdb_target_obs="i386-cygwin-tdep.o windows-tdep.o"
+ gdb_target_obs="i386-windows-tdep.o windows-tdep.o"
  ;;
 i[34567]86-*-go32* | i[34567]86-*-msdosdjgpp*)
  # Target: i386 running DJGPP/go32.
@@ -730,7 +730,7 @@ x86_64-*-freebsd* | x86_64-*-kfreebsd*-gnu)
 x86_64-*-mingw* | x86_64-*-cygwin*)
         # Target: MingW/amd64
  gdb_target_obs="amd64-windows-tdep.o \
-                        ${i386_tobjs} i386-cygwin-tdep.o \
+                        ${i386_tobjs} i386-windows-tdep.o \
                         windows-tdep.o"
         ;;
 x86_64-*-netbsd* | x86_64-*-knetbsd*-gnu)
diff --git a/gdb/i386-cygwin-tdep.c b/gdb/i386-windows-tdep.c
similarity index 100%
rename from gdb/i386-cygwin-tdep.c
rename to gdb/i386-windows-tdep.c
--
2.25.1

Reply | Threaded
Open this post in threaded view
|

[PATCH 5/7] gdb: rename content of i386-windows-tdep.c, cygwin to windows

Sourceware - gdb-patches mailing list
In reply to this post by Sourceware - gdb-patches mailing list
From: Simon Marchi <[hidden email]>

i386-cygwin-tdep.c has just been renamed to i386-windows-tdep.c, this
patch now renames everything in it that is not Cygwin-specific to
replace "cygwin" with "windows".

Note that I did not rename i386_cygwin_core_osabi_sniffer, since that
appears to be Cygwin-specific.

gdb/ChangeLog:

        * i386-windows-tdep.c: Mass-rename "cygwin" to "windows", except
        i386_cygwin_core_osabi_sniffer.
---
 gdb/i386-windows-tdep.c | 31 ++++++++++++++++---------------
 1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/gdb/i386-windows-tdep.c b/gdb/i386-windows-tdep.c
index b9a959d3c7d4..a71ceda781f8 100644
--- a/gdb/i386-windows-tdep.c
+++ b/gdb/i386-windows-tdep.c
@@ -1,4 +1,5 @@
-/* Target-dependent code for Cygwin running on i386's, for GDB.
+/* Target-dependent code for Windows (including Cygwin) running on i386's,
+   for GDB.
 
    Copyright (C) 2003-2020 Free Software Foundation, Inc.
 
@@ -188,25 +189,25 @@ i386_windows_core_pid_to_str (struct gdbarch *gdbarch, ptid_t ptid)
 }
 
 static CORE_ADDR
-i386_cygwin_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
+i386_windows_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
 {
   return i386_pe_skip_trampoline_code (frame, pc, NULL);
 }
 
 static const char *
-i386_cygwin_auto_wide_charset (void)
+i386_windows_auto_wide_charset (void)
 {
   return "UTF-16";
 }
 
 static void
-i386_cygwin_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+i386_windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   windows_init_abi (info, gdbarch);
 
-  set_gdbarch_skip_trampoline_code (gdbarch, i386_cygwin_skip_trampoline_code);
+  set_gdbarch_skip_trampoline_code (gdbarch, i386_windows_skip_trampoline_code);
 
   set_gdbarch_skip_main_prologue (gdbarch, i386_skip_main_prologue);
 
@@ -223,11 +224,11 @@ i386_cygwin_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
     (gdbarch, windows_core_xfer_shared_libraries);
   set_gdbarch_core_pid_to_str (gdbarch, i386_windows_core_pid_to_str);
 
-  set_gdbarch_auto_wide_charset (gdbarch, i386_cygwin_auto_wide_charset);
+  set_gdbarch_auto_wide_charset (gdbarch, i386_windows_auto_wide_charset);
 }
 
-static enum gdb_osabi
-i386_cygwin_osabi_sniffer (bfd *abfd)
+static gdb_osabi
+i386_windows_osabi_sniffer (bfd *abfd)
 {
   const char *target_name = bfd_get_target (abfd);
 
@@ -255,20 +256,20 @@ i386_cygwin_core_osabi_sniffer (bfd *abfd)
   return GDB_OSABI_UNKNOWN;
 }
 
-void _initialize_i386_cygwin_tdep ();
+void _initialize_i386_windows_tdep ();
 void
-_initialize_i386_cygwin_tdep ()
+_initialize_i386_windows_tdep ()
 {
   gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
-                                  i386_cygwin_osabi_sniffer);
+                                  i386_windows_osabi_sniffer);
 
   /* Cygwin uses elf core dumps.  */
   gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour,
                                   i386_cygwin_core_osabi_sniffer);
 
-  /* The Cygwin and Windows OS ABIs are currently equivalent.  */
-  gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_CYGWIN,
-                          i386_cygwin_init_abi);
+  /* The Windows and Cygwin OS ABIs are currently equivalent.  */
   gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_WINDOWS,
-                          i386_cygwin_init_abi);
+                          i386_windows_init_abi);
+  gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_CYGWIN,
+                          i386_windows_init_abi);
 }
--
2.25.1

Reply | Threaded
Open this post in threaded view
|

[PATCH 6/7] gdb: select "Cygwin" OS ABI for Cygwin binaries

Sourceware - gdb-patches mailing list
In reply to this post by Sourceware - gdb-patches mailing list
From: Simon Marchi <[hidden email]>

Before this patch, the "Windows" OS ABI is selected for all Windows
executables, including Cygwin ones.  This patch makes GDB differentiate
Cygwin binaries from non-Cygwin ones, and selects the "Cygwin" OS ABI
for the Cygwin ones.

To check whether a Windows PE executable is a Cygwin one, we check the
library list in the .idata section, see if it contains "cygwin1.dll".

I had to add code to parse the .idata section, because BFD doesn't seem
to expose this information.  BFD does parse this information, but only
to print it in textual form (function pe_print_idata):

  https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=blob;f=bfd/peXXigen.c;h=e42d646552a0ca1e856e082256cd3d943b54ddf0;hb=HEAD#l1261

Here's the relevant portion of the PE format documentation:

  https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-idata-section

This page was also useful:

  https://blog.kowalczyk.info/articles/pefileformat.html#9ccef823-67e7-4372-9172-045d7b1fb006

With this patch applied, this is what I get:

    (gdb) file some_mingw_x86_64_binary.exe
    Reading symbols from some_mingw_x86_64_binary.exe...
    (gdb) show osabi
    The current OS ABI is "auto" (currently "Windows").
    The default OS ABI is "GNU/Linux".

    (gdb) file some_mingw_i386_binary.exe
    Reading symbols from some_mingw_i386_binary.exe...
    (gdb) show osabi
    The current OS ABI is "auto" (currently "Windows").
    The default OS ABI is "GNU/Linux".

    (gdb) file some_cygwin_x86_64_binary.exe
    Reading symbols from some_cygwin_x86_64_binary.exe...
    (gdb) show osabi
    The current OS ABI is "auto" (currently "Cygwin").
    The default OS ABI is "GNU/Linux".

gdb/ChangeLog:

        * windows-tdep.h (is_linked_with_cygwin_dll): New declaration.
        * windows-tdep.c (CYGWIN_DLL_NAME): New.
        (pe_import_directory_entry): New struct type.
        (is_linked_with_cygwin_dll): New function.
        * amd64-windows-tdep.c (amd64_windows_osabi_sniffer): Select
        GDB_OSABI_CYGWIN if the BFD is linked with the Cygwin DLL.
        * i386-windows-tdep.c (i386_windows_osabi_sniffer): Likewise.
---
 gdb/amd64-windows-tdep.c |   9 ++--
 gdb/i386-windows-tdep.c  |   9 ++--
 gdb/windows-tdep.c       | 101 +++++++++++++++++++++++++++++++++++++++
 gdb/windows-tdep.h       |   6 +++
 4 files changed, 119 insertions(+), 6 deletions(-)

diff --git a/gdb/amd64-windows-tdep.c b/gdb/amd64-windows-tdep.c
index 88ff794abcb6..e0346f8628fe 100644
--- a/gdb/amd64-windows-tdep.c
+++ b/gdb/amd64-windows-tdep.c
@@ -1249,10 +1249,13 @@ amd64_windows_osabi_sniffer (bfd *abfd)
 {
   const char *target_name = bfd_get_target (abfd);
 
-  if (strcmp (target_name, "pei-x86-64") == 0)
-    return GDB_OSABI_WINDOWS;
+  if (!streq (target_name, "pei-x86-64"))
+    return GDB_OSABI_UNKNOWN;
 
-  return GDB_OSABI_UNKNOWN;
+  if (is_linked_with_cygwin_dll (abfd))
+    return GDB_OSABI_CYGWIN;
+
+  return GDB_OSABI_WINDOWS;
 }
 
 void _initialize_amd64_windows_tdep ();
diff --git a/gdb/i386-windows-tdep.c b/gdb/i386-windows-tdep.c
index a71ceda781f8..bd6107b02f1f 100644
--- a/gdb/i386-windows-tdep.c
+++ b/gdb/i386-windows-tdep.c
@@ -232,10 +232,13 @@ i386_windows_osabi_sniffer (bfd *abfd)
 {
   const char *target_name = bfd_get_target (abfd);
 
-  if (strcmp (target_name, "pei-i386") == 0)
-    return GDB_OSABI_WINDOWS;
+  if (!streq (target_name, "pei-i386"))
+    return GDB_OSABI_UNKNOWN;
 
-  return GDB_OSABI_UNKNOWN;
+  if (is_linked_with_cygwin_dll (abfd))
+    return GDB_OSABI_CYGWIN;
+
+  return GDB_OSABI_WINDOWS;
 }
 
 static enum gdb_osabi
diff --git a/gdb/windows-tdep.c b/gdb/windows-tdep.c
index e02b1ceed387..32e551bcb175 100644
--- a/gdb/windows-tdep.c
+++ b/gdb/windows-tdep.c
@@ -38,6 +38,8 @@
 #include "libcoff.h"
 #include "solist.h"
 
+#define CYGWIN_DLL_NAME "cygwin1.dll"
+
 /* Windows signal numbers differ between MinGW flavors and between
    those and Cygwin.  The below enumeration was gleaned from the
    respective headers; the ones marked with MinGW64/Cygwin are defined
@@ -898,6 +900,105 @@ static const struct internalvar_funcs tlb_funcs =
   NULL
 };
 
+/* Layout of an element of a PE's Import Directory Table.  Based on:
+
+     https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-directory-table
+ */
+
+struct pe_import_directory_entry
+{
+  uint32_t import_lookup_table_rva;
+  uint32_t timestamp;
+  uint32_t forwarder_chain;
+  uint32_t name_rva;
+  uint32_t import_address_table_rva;
+};
+
+gdb_static_assert (sizeof (pe_import_directory_entry) == 20);
+
+/* Return true if the Portable Executable behind ABFD uses the Cygwin dll
+   (cygwin1.dll). */
+/* See windows-tdep.h.  */
+
+bool
+is_linked_with_cygwin_dll (bfd *abfd)
+{
+  /* The list of DLLs a PE is linked to is in the .idata section.  See:
+
+     https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-idata-section
+   */
+  asection *idata_section = bfd_get_section_by_name (abfd, ".idata");
+  if (idata_section == nullptr)
+    return false;
+
+  /* Find the virtual address of the .idata section.  We must subtract this
+     from the RVAs (relative virtual addresses) to obtain an offset in the
+     section. */
+  bfd_vma idata_addr =
+    pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_TABLE].VirtualAddress;
+
+  /* Map the section's data.  */
+  bfd_size_type idata_size;
+  const gdb_byte *const idata_contents
+    = gdb_bfd_map_section (idata_section, &idata_size);
+  if (idata_contents == nullptr)
+    {
+      warning (_("Failed to get content of .idata section."));
+      return false;
+    }
+
+  const gdb_byte *iter = idata_contents;
+  const gdb_byte *end = idata_contents + idata_size;
+  const pe_import_directory_entry null_dir_entry = { 0 };
+
+  /* Iterate through all directory entries.  */
+  while (true)
+    {
+      /* Is there enough space left in the section for another entry?  */
+      if (iter + sizeof (pe_import_directory_entry) > end)
+ {
+  warning (_("Failed to parse .idata section: unexpected end of "
+     ".idata section."));
+  break;
+ }
+
+      pe_import_directory_entry *dir_entry = (pe_import_directory_entry *) iter;
+
+      /* Is it the end of list marker?  */
+      if (memcmp (dir_entry, &null_dir_entry,
+  sizeof (pe_import_directory_entry)) == 0)
+ break;
+
+      bfd_vma name_addr = dir_entry->name_rva;
+
+      /* If the name's virtual address is smaller than the section's virtual
+         address, there's a problem.  */
+      if (name_addr < idata_addr
+  || name_addr >= (idata_addr + idata_size))
+ {
+  warning (_("\
+Failed to parse .idata section: name's virtual address (0x%" BFD_VMA_FMT "x) \
+is outside .idata section's range [0x%" BFD_VMA_FMT "x, 0x%" BFD_VMA_FMT "x[."),
+   name_addr, idata_addr, idata_addr + idata_size);
+  break;
+ }
+
+      const gdb_byte *name = &idata_contents[name_addr - idata_addr];
+
+      /* Make sure we don't overshoot the end of the section with the streq.  */
+      if (name + sizeof(CYGWIN_DLL_NAME) > end)
+ continue;
+
+      /* Finally, check if this is the dll name we are looking for.  */
+      if (streq ((const char *) name, CYGWIN_DLL_NAME))
+ return true;
+
+      iter += sizeof(pe_import_directory_entry);
+    }
+
+    return false;
+}
+
 void _initialize_windows_tdep ();
 void
 _initialize_windows_tdep ()
diff --git a/gdb/windows-tdep.h b/gdb/windows-tdep.h
index 34474f259c2a..f2dc4260469d 100644
--- a/gdb/windows-tdep.h
+++ b/gdb/windows-tdep.h
@@ -33,4 +33,10 @@ extern void windows_xfer_shared_library (const char* so_name,
 
 extern void windows_init_abi (struct gdbarch_info info,
       struct gdbarch *gdbarch);
+
+/* Return true if the Portable Executable behind ABFD uses the Cygwin dll
+   (cygwin1.dll).  */
+
+extern bool is_linked_with_cygwin_dll (bfd *abfd);
+
 #endif
--
2.25.1

Reply | Threaded
Open this post in threaded view
|

[PATCH 7/7] gdb: define builtin long type to be 64 bits on amd64 Cygwin

Sourceware - gdb-patches mailing list
In reply to this post by Sourceware - gdb-patches mailing list
From: Simon Marchi <[hidden email]>

On Windows x86-64 (when building with MinGW), the size of the "long"
type is 32 bits.  amd64_windows_init_abi therefore does:

    set_gdbarch_long_bit (gdbarch, 32);

This is also used when the chosen OS ABI is Cygwin, where the "long"
type is 64 bits.  GDB therefore gets sizeof(long) wrong when using the
builtin long type:

    $ ./gdb -nx --data-directory=data-directory -batch -ex "set architecture i386:x86-64" -ex "set osabi Cygwin" -ex "print sizeof(long)"
    The target architecture is assumed to be i386:x86-64
    $1 = 4

This patch makes GDB avoid setting the size of the long type to 32 bits
when using the Cygwin OS ABI.  it will inherit the value set in
amd64_init_abi.

With this patch, I get:

    $ ./gdb -nx --data-directory=data-directory -batch -ex "set architecture i386:x86-64" -ex "set osabi Cygwin" -ex "print sizeof(long)"
    The target architecture is assumed to be i386:x86-64
    $1 = 8

gdb/ChangeLog:

        PR gdb/21500
        * amd64-windows-tdep.c (amd64_windows_init_abi): Rename
        to...
        (amd64_windows_init_abi_common): ... this.  Don't set size of
        long type.
        (amd64_windows_init_abi): New function.
        (amd64_cygwin_init_abi): New function.
        (_initialize_amd64_windows_tdep): Use amd64_cygwin_init_abi for
        the Cygwin OS ABI.
        * i386-windows-tdep.c (_initialize_i386_windows_tdep): Clarify
        comment.
---
 gdb/amd64-windows-tdep.c | 23 +++++++++++++++++------
 gdb/i386-windows-tdep.c  |  2 +-
 2 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/gdb/amd64-windows-tdep.c b/gdb/amd64-windows-tdep.c
index e0346f8628fe..6d5076d1c437 100644
--- a/gdb/amd64-windows-tdep.c
+++ b/gdb/amd64-windows-tdep.c
@@ -1209,7 +1209,7 @@ amd64_windows_auto_wide_charset (void)
 }
 
 static void
-amd64_windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+amd64_windows_init_abi_common (gdbarch_info info, struct gdbarch *gdbarch)
 {
   /* The dwarf2 unwinder (appended very early by i386_gdbarch_init) is
      preferred over the SEH one.  The reasons are:
@@ -1229,9 +1229,6 @@ amd64_windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 
   windows_init_abi (info, gdbarch);
 
-  /* On Windows, "long"s are only 32bit.  */
-  set_gdbarch_long_bit (gdbarch, 32);
-
   /* Function calls.  */
   set_gdbarch_push_dummy_call (gdbarch, amd64_windows_push_dummy_call);
   set_gdbarch_return_value (gdbarch, amd64_windows_return_value);
@@ -1244,6 +1241,21 @@ amd64_windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_gdbarch_auto_wide_charset (gdbarch, amd64_windows_auto_wide_charset);
 }
 
+static void
+amd64_windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  amd64_windows_init_abi_common (info, gdbarch);
+
+  /* On Windows, "long"s are only 32bit.  */
+  set_gdbarch_long_bit (gdbarch, 32);
+}
+
+static void
+amd64_cygwin_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  amd64_windows_init_abi_common (info, gdbarch);
+}
+
 static gdb_osabi
 amd64_windows_osabi_sniffer (bfd *abfd)
 {
@@ -1262,11 +1274,10 @@ void _initialize_amd64_windows_tdep ();
 void
 _initialize_amd64_windows_tdep ()
 {
-  /* The Cygwin and Windows OS ABIs are currently equivalent.  */
   gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, GDB_OSABI_WINDOWS,
                           amd64_windows_init_abi);
   gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, GDB_OSABI_CYGWIN,
-                          amd64_windows_init_abi);
+                          amd64_cygwin_init_abi);
 
   gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
   amd64_windows_osabi_sniffer);
diff --git a/gdb/i386-windows-tdep.c b/gdb/i386-windows-tdep.c
index bd6107b02f1f..b26731c6bf28 100644
--- a/gdb/i386-windows-tdep.c
+++ b/gdb/i386-windows-tdep.c
@@ -270,7 +270,7 @@ _initialize_i386_windows_tdep ()
   gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour,
                                   i386_cygwin_core_osabi_sniffer);
 
-  /* The Windows and Cygwin OS ABIs are currently equivalent.  */
+  /* The Windows and Cygwin OS ABIs are currently equivalent on i386.  */
   gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_WINDOWS,
                           i386_windows_init_abi);
   gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_CYGWIN,
--
2.25.1

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 0/7] Add "Windows" OS ABI

Eli Zaretskii
In reply to this post by Sourceware - gdb-patches mailing list
> From: Simon Marchi <[hidden email]>
> Cc: Eli Zaretskii <[hidden email]>,
> Jon Turney <[hidden email]>,
> Simon Marchi <[hidden email]>
> Date: Mon, 16 Mar 2020 13:08:38 -0400
>
> This patchset started out as a single patch to have the OS ABI Cygwin
> applied to Windows x86-64 binaries, here:
>
>     https://sourceware.org/legacy-ml/gdb-patches/2020-03/msg00195.html
>
> with the follow-up here:
>
>     https://sourceware.org/pipermail/gdb-patches/2020-March/000022.html
>
> Eli pointed out that it doesn't make sense for binaries compilied with
> MinGW to have the Cygwin OS ABI, that there should be separate OS ABIs
> for Cygwin and non-Cygwin Windows binaries.  This already came up in the
> following bug report:
>
>     https://sourceware.org/bugzilla/show_bug.cgi?id=21500#add_comment
>
> This patchset does a bit of refactor in that area.  Most importantly, it:
>
> - adds a "Windows" OS ABI
> - makes GDB recognize the proper OS ABI (Cygwin or Windows) when
>   loading executables
> - makes the builtin long type on Cygwin be 64 bits long

Thanks for working on this, the changes LGTM.
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 0/7] Add "Windows" OS ABI

Sourceware - gdb-patches mailing list
On 2020-03-16 1:46 p.m., Eli Zaretskii wrote:

>> From: Simon Marchi <[hidden email]>
>> Cc: Eli Zaretskii <[hidden email]>,
>> Jon Turney <[hidden email]>,
>> Simon Marchi <[hidden email]>
>> Date: Mon, 16 Mar 2020 13:08:38 -0400
>>
>> This patchset started out as a single patch to have the OS ABI Cygwin
>> applied to Windows x86-64 binaries, here:
>>
>>     https://sourceware.org/legacy-ml/gdb-patches/2020-03/msg00195.html
>>
>> with the follow-up here:
>>
>>     https://sourceware.org/pipermail/gdb-patches/2020-March/000022.html
>>
>> Eli pointed out that it doesn't make sense for binaries compilied with
>> MinGW to have the Cygwin OS ABI, that there should be separate OS ABIs
>> for Cygwin and non-Cygwin Windows binaries.  This already came up in the
>> following bug report:
>>
>>     https://sourceware.org/bugzilla/show_bug.cgi?id=21500#add_comment
>>
>> This patchset does a bit of refactor in that area.  Most importantly, it:
>>
>> - adds a "Windows" OS ABI
>> - makes GDB recognize the proper OS ABI (Cygwin or Windows) when
>>   loading executables
>> - makes the builtin long type on Cygwin be 64 bits long
>
> Thanks for working on this, the changes LGTM.
>

Thanks for taking a look, I'll give a bit more time for others (Jon might be
interested) to take a look if and comment.

Simon
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 6/7] gdb: select "Cygwin" OS ABI for Cygwin binaries

Sourceware - gdb-patches mailing list
In reply to this post by Sourceware - gdb-patches mailing list
On Mon, Mar 16, 2020 at 12:09 PM Simon Marchi via Gdb-patches
<[hidden email]> wrote:

>
> From: Simon Marchi <[hidden email]>
>
> Before this patch, the "Windows" OS ABI is selected for all Windows
> executables, including Cygwin ones.  This patch makes GDB differentiate
> Cygwin binaries from non-Cygwin ones, and selects the "Cygwin" OS ABI
> for the Cygwin ones.
>
> To check whether a Windows PE executable is a Cygwin one, we check the
> library list in the .idata section, see if it contains "cygwin1.dll".
>
> I had to add code to parse the .idata section, because BFD doesn't seem
> to expose this information.  BFD does parse this information, but only
> to print it in textual form (function pe_print_idata):
>
>   https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=blob;f=bfd/peXXigen.c;h=e42d646552a0ca1e856e082256cd3d943b54ddf0;hb=HEAD#l1261
>
> Here's the relevant portion of the PE format documentation:
>
>   https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-idata-section
>
> This page was also useful:
>
>   https://blog.kowalczyk.info/articles/pefileformat.html#9ccef823-67e7-4372-9172-045d7b1fb006
>
> With this patch applied, this is what I get:
>
>     (gdb) file some_mingw_x86_64_binary.exe
>     Reading symbols from some_mingw_x86_64_binary.exe...
>     (gdb) show osabi
>     The current OS ABI is "auto" (currently "Windows").
>     The default OS ABI is "GNU/Linux".
>
>     (gdb) file some_mingw_i386_binary.exe
>     Reading symbols from some_mingw_i386_binary.exe...
>     (gdb) show osabi
>     The current OS ABI is "auto" (currently "Windows").
>     The default OS ABI is "GNU/Linux".
>
>     (gdb) file some_cygwin_x86_64_binary.exe
>     Reading symbols from some_cygwin_x86_64_binary.exe...
>     (gdb) show osabi
>     The current OS ABI is "auto" (currently "Cygwin").
>     The default OS ABI is "GNU/Linux".
>
> gdb/ChangeLog:
>
>         * windows-tdep.h (is_linked_with_cygwin_dll): New declaration.
>         * windows-tdep.c (CYGWIN_DLL_NAME): New.
>         (pe_import_directory_entry): New struct type.
>         (is_linked_with_cygwin_dll): New function.
>         * amd64-windows-tdep.c (amd64_windows_osabi_sniffer): Select
>         GDB_OSABI_CYGWIN if the BFD is linked with the Cygwin DLL.
>         * i386-windows-tdep.c (i386_windows_osabi_sniffer): Likewise.
> ---
>  gdb/amd64-windows-tdep.c |   9 ++--
>  gdb/i386-windows-tdep.c  |   9 ++--
>  gdb/windows-tdep.c       | 101 +++++++++++++++++++++++++++++++++++++++
>  gdb/windows-tdep.h       |   6 +++
>  4 files changed, 119 insertions(+), 6 deletions(-)
>
> diff --git a/gdb/amd64-windows-tdep.c b/gdb/amd64-windows-tdep.c
> index 88ff794abcb6..e0346f8628fe 100644
> --- a/gdb/amd64-windows-tdep.c
> +++ b/gdb/amd64-windows-tdep.c
> @@ -1249,10 +1249,13 @@ amd64_windows_osabi_sniffer (bfd *abfd)
>  {
>    const char *target_name = bfd_get_target (abfd);
>
> -  if (strcmp (target_name, "pei-x86-64") == 0)
> -    return GDB_OSABI_WINDOWS;
> +  if (!streq (target_name, "pei-x86-64"))
> +    return GDB_OSABI_UNKNOWN;
>
> -  return GDB_OSABI_UNKNOWN;
> +  if (is_linked_with_cygwin_dll (abfd))
> +    return GDB_OSABI_CYGWIN;
> +
> +  return GDB_OSABI_WINDOWS;
>  }
>
>  void _initialize_amd64_windows_tdep ();
> diff --git a/gdb/i386-windows-tdep.c b/gdb/i386-windows-tdep.c
> index a71ceda781f8..bd6107b02f1f 100644
> --- a/gdb/i386-windows-tdep.c
> +++ b/gdb/i386-windows-tdep.c
> @@ -232,10 +232,13 @@ i386_windows_osabi_sniffer (bfd *abfd)
>  {
>    const char *target_name = bfd_get_target (abfd);
>
> -  if (strcmp (target_name, "pei-i386") == 0)
> -    return GDB_OSABI_WINDOWS;
> +  if (!streq (target_name, "pei-i386"))
> +    return GDB_OSABI_UNKNOWN;
>
> -  return GDB_OSABI_UNKNOWN;
> +  if (is_linked_with_cygwin_dll (abfd))
> +    return GDB_OSABI_CYGWIN;
> +
> +  return GDB_OSABI_WINDOWS;
>  }
>
>  static enum gdb_osabi
> diff --git a/gdb/windows-tdep.c b/gdb/windows-tdep.c
> index e02b1ceed387..32e551bcb175 100644
> --- a/gdb/windows-tdep.c
> +++ b/gdb/windows-tdep.c
> @@ -38,6 +38,8 @@
>  #include "libcoff.h"
>  #include "solist.h"
>
> +#define CYGWIN_DLL_NAME "cygwin1.dll"
> +
>  /* Windows signal numbers differ between MinGW flavors and between
>     those and Cygwin.  The below enumeration was gleaned from the
>     respective headers; the ones marked with MinGW64/Cygwin are defined
> @@ -898,6 +900,105 @@ static const struct internalvar_funcs tlb_funcs =
>    NULL
>  };
>
> +/* Layout of an element of a PE's Import Directory Table.  Based on:
> +
> +     https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-directory-table
> + */
> +
> +struct pe_import_directory_entry
> +{
> +  uint32_t import_lookup_table_rva;
> +  uint32_t timestamp;
> +  uint32_t forwarder_chain;
> +  uint32_t name_rva;
> +  uint32_t import_address_table_rva;
> +};
> +
> +gdb_static_assert (sizeof (pe_import_directory_entry) == 20);
> +
> +/* Return true if the Portable Executable behind ABFD uses the Cygwin dll
> +   (cygwin1.dll). */
> +/* See windows-tdep.h.  */

Remove the first of these two comments?

> +
> +bool
> +is_linked_with_cygwin_dll (bfd *abfd)
> +{
> +  /* The list of DLLs a PE is linked to is in the .idata section.  See:
> +
> +     https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-idata-section
> +   */
> +  asection *idata_section = bfd_get_section_by_name (abfd, ".idata");
> +  if (idata_section == nullptr)
> +    return false;
> +
> +  /* Find the virtual address of the .idata section.  We must subtract this
> +     from the RVAs (relative virtual addresses) to obtain an offset in the
> +     section. */
> +  bfd_vma idata_addr =
> +    pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_TABLE].VirtualAddress;
> +
> +  /* Map the section's data.  */
> +  bfd_size_type idata_size;
> +  const gdb_byte *const idata_contents
> +    = gdb_bfd_map_section (idata_section, &idata_size);
> +  if (idata_contents == nullptr)
> +    {
> +      warning (_("Failed to get content of .idata section."));
> +      return false;
> +    }
> +
> +  const gdb_byte *iter = idata_contents;
> +  const gdb_byte *end = idata_contents + idata_size;
> +  const pe_import_directory_entry null_dir_entry = { 0 };
> +
> +  /* Iterate through all directory entries.  */
> +  while (true)
> +    {
> +      /* Is there enough space left in the section for another entry?  */
> +      if (iter + sizeof (pe_import_directory_entry) > end)
> +       {
> +         warning (_("Failed to parse .idata section: unexpected end of "
> +                    ".idata section."));
> +         break;
> +       }
> +
> +      pe_import_directory_entry *dir_entry = (pe_import_directory_entry *) iter;
> +
> +      /* Is it the end of list marker?  */
> +      if (memcmp (dir_entry, &null_dir_entry,
> +                 sizeof (pe_import_directory_entry)) == 0)
> +       break;
> +
> +      bfd_vma name_addr = dir_entry->name_rva;
> +
> +      /* If the name's virtual address is smaller than the section's virtual
> +         address, there's a problem.  */
> +      if (name_addr < idata_addr
> +         || name_addr >= (idata_addr + idata_size))
> +       {
> +         warning (_("\
> +Failed to parse .idata section: name's virtual address (0x%" BFD_VMA_FMT "x) \
> +is outside .idata section's range [0x%" BFD_VMA_FMT "x, 0x%" BFD_VMA_FMT "x[."),
> +                  name_addr, idata_addr, idata_addr + idata_size);
> +         break;
> +       }
> +
> +      const gdb_byte *name = &idata_contents[name_addr - idata_addr];
> +
> +      /* Make sure we don't overshoot the end of the section with the streq.  */
> +      if (name + sizeof(CYGWIN_DLL_NAME) > end)
> +       continue;
> +
> +      /* Finally, check if this is the dll name we are looking for.  */
> +      if (streq ((const char *) name, CYGWIN_DLL_NAME))
> +       return true;
> +
> +      iter += sizeof(pe_import_directory_entry);
> +    }
> +
> +    return false;
> +}
> +
>  void _initialize_windows_tdep ();
>  void
>  _initialize_windows_tdep ()
> diff --git a/gdb/windows-tdep.h b/gdb/windows-tdep.h
> index 34474f259c2a..f2dc4260469d 100644
> --- a/gdb/windows-tdep.h
> +++ b/gdb/windows-tdep.h
> @@ -33,4 +33,10 @@ extern void windows_xfer_shared_library (const char* so_name,
>
>  extern void windows_init_abi (struct gdbarch_info info,
>                               struct gdbarch *gdbarch);
> +
> +/* Return true if the Portable Executable behind ABFD uses the Cygwin dll
> +   (cygwin1.dll).  */
> +
> +extern bool is_linked_with_cygwin_dll (bfd *abfd);
> +
>  #endif
> --
> 2.25.1
>
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 6/7] gdb: select "Cygwin" OS ABI for Cygwin binaries

Sourceware - gdb-patches mailing list
On 2020-03-16 2:16 p.m., Christian Biesinger wrote:

>> @@ -898,6 +900,105 @@ static const struct internalvar_funcs tlb_funcs =
>>    NULL
>>  };
>>
>> +/* Layout of an element of a PE's Import Directory Table.  Based on:
>> +
>> +     https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-directory-table
>> + */
>> +
>> +struct pe_import_directory_entry
>> +{
>> +  uint32_t import_lookup_table_rva;
>> +  uint32_t timestamp;
>> +  uint32_t forwarder_chain;
>> +  uint32_t name_rva;
>> +  uint32_t import_address_table_rva;
>> +};
>> +
>> +gdb_static_assert (sizeof (pe_import_directory_entry) == 20);
>> +
>> +/* Return true if the Portable Executable behind ABFD uses the Cygwin dll
>> +   (cygwin1.dll). */
>> +/* See windows-tdep.h.  */
>
> Remove the first of these two comments?

Indeed, thanks.

Simon

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 6/7] gdb: select "Cygwin" OS ABI for Cygwin binaries

Jon TURNEY
In reply to this post by Sourceware - gdb-patches mailing list
On 16/03/2020 17:08, Simon Marchi wrote:

> From: Simon Marchi <[hidden email]>
>
> Before this patch, the "Windows" OS ABI is selected for all Windows
> executables, including Cygwin ones.  This patch makes GDB differentiate
> Cygwin binaries from non-Cygwin ones, and selects the "Cygwin" OS ABI
> for the Cygwin ones.
>
> To check whether a Windows PE executable is a Cygwin one, we check the
> library list in the .idata section, see if it contains "cygwin1.dll".
>
> I had to add code to parse the .idata section, because BFD doesn't seem
> to expose this information.  BFD does parse this information, but only
> to print it in textual form (function pe_print_idata):
>
[...]

> +
> +bool
> +is_linked_with_cygwin_dll (bfd *abfd)
> +{
> +  /* The list of DLLs a PE is linked to is in the .idata section.  See:
> +
> +     https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-idata-section
> +   */
> +  asection *idata_section = bfd_get_section_by_name (abfd, ".idata");
> +  if (idata_section == nullptr)
> +    return false;

I'm fine with this as-is, but FTR I think this only happens to work
because binutils ld (which is probably the only way to currently build a
cygwin executable) puts the import table in the .idata section.

The strictly correct way to locate the import table is to use the data
directory (as pe_print_idata() does)

(See
https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#optional-header-data-directories-image-only)

(Notwithstanding the MS documentation you linked, I believe MS tools can
put the import table in .rdata)
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 0/7] Add "Windows" OS ABI

Jon TURNEY
In reply to this post by Sourceware - gdb-patches mailing list
On 16/03/2020 17:48, Simon Marchi wrote:

> On 2020-03-16 1:46 p.m., Eli Zaretskii wrote:
>>> From: Simon Marchi <[hidden email]>
>>> Cc: Eli Zaretskii <[hidden email]>,
>>> Jon Turney <[hidden email]>,
>>> Simon Marchi <[hidden email]>
>>> Date: Mon, 16 Mar 2020 13:08:38 -0400
>>>
>>> This patchset started out as a single patch to have the OS ABI Cygwin
>>> applied to Windows x86-64 binaries, here:
>>>
>>>      https://sourceware.org/legacy-ml/gdb-patches/2020-03/msg00195.html
>>>
>>> with the follow-up here:
>>>
>>>      https://sourceware.org/pipermail/gdb-patches/2020-March/000022.html
>>>
>>> Eli pointed out that it doesn't make sense for binaries compilied with
>>> MinGW to have the Cygwin OS ABI, that there should be separate OS ABIs
>>> for Cygwin and non-Cygwin Windows binaries.  This already came up in the
>>> following bug report:
>>>
>>>      https://sourceware.org/bugzilla/show_bug.cgi?id=21500#add_comment
>>>
>>> This patchset does a bit of refactor in that area.  Most importantly, it:
>>>
>>> - adds a "Windows" OS ABI
>>> - makes GDB recognize the proper OS ABI (Cygwin or Windows) when
>>>    loading executables
>>> - makes the builtin long type on Cygwin be 64 bits long
>>
>> Thanks for working on this, the changes LGTM.
>>
>
> Thanks for taking a look, I'll give a bit more time for others (Jon might be
> interested) to take a look if and comment.

Patches look good, and appear work correctly in some brief testing.
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 6/7] gdb: select "Cygwin" OS ABI for Cygwin binaries

Sourceware - gdb-patches mailing list
In reply to this post by Jon TURNEY
On 2020-03-16 3:03 p.m., Jon Turney wrote:

>> +bool
>> +is_linked_with_cygwin_dll (bfd *abfd)
>> +{
>> +  /* The list of DLLs a PE is linked to is in the .idata section.  See:
>> +
>> +     https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-idata-section
>> +   */
>> +  asection *idata_section = bfd_get_section_by_name (abfd, ".idata");
>> +  if (idata_section == nullptr)
>> +    return false;
>
> I'm fine with this as-is, but FTR I think this only happens to work
> because binutils ld (which is probably the only way to currently build a
> cygwin executable) puts the import table in the .idata section.
>
> The strictly correct way to locate the import table is to use the data
> directory (as pe_print_idata() does)
>
> (See
> https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#optional-header-data-directories-image-only)
>
> (Notwithstanding the MS documentation you linked, I believe MS tools can
> put the import table in .rdata)
>

After clarification with Jon on IRC, the current code is sufficient for the
moment.

I've pushed the series, thanks.

Simon
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 6/7] gdb: select "Cygwin" OS ABI for Cygwin binaries

Tom Tromey-2
In reply to this post by Sourceware - gdb-patches mailing list
>>>>> "Simon" == Simon Marchi via Gdb-patches <[hidden email]> writes:

Simon> +  warning (_("\
Simon> +Failed to parse .idata section: name's virtual address (0x%" BFD_VMA_FMT "x) \
Simon> +is outside .idata section's range [0x%" BFD_VMA_FMT "x, 0x%" BFD_VMA_FMT "x[."),
Simon> +   name_addr, idata_addr, idata_addr + idata_size);

Our internal test suite has started failing a test due to this output:

     warning: Failed to parse .idata section: name's virtual address (0x1) is outside .idata section's range [0x120500, 0x12bd64[.
     warning: Failed to parse .idata section: name's virtual address (0x1) is outside .idata section's range [0xea210, 0xefbb0[.
     warning: Failed to parse .idata section: name's virtual address (0x1) is outside .idata section's range [0x9b578, 0x9d042[.

I assume this is a bug in this code?  I don't really know.

Are there known problems here?

I can probably get you an executable if that would help.
("Probably" because I haven't tried to reproduce by hand, I've only seen
it in automation, and I'd have to do it by hand to get the exe.)

Tom
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 6/7] gdb: select "Cygwin" OS ABI for Cygwin binaries

Sourceware - gdb-patches mailing list
On 2020-04-01 3:05 p.m., Tom Tromey wrote:

>>>>>> "Simon" == Simon Marchi via Gdb-patches <[hidden email]> writes:
>
> Simon> +  warning (_("\
> Simon> +Failed to parse .idata section: name's virtual address (0x%" BFD_VMA_FMT "x) \
> Simon> +is outside .idata section's range [0x%" BFD_VMA_FMT "x, 0x%" BFD_VMA_FMT "x[."),
> Simon> +   name_addr, idata_addr, idata_addr + idata_size);
>
> Our internal test suite has started failing a test due to this output:
>
>      warning: Failed to parse .idata section: name's virtual address (0x1) is outside .idata section's range [0x120500, 0x12bd64[.
>      warning: Failed to parse .idata section: name's virtual address (0x1) is outside .idata section's range [0xea210, 0xefbb0[.
>      warning: Failed to parse .idata section: name's virtual address (0x1) is outside .idata section's range [0x9b578, 0x9d042[.
>
> I assume this is a bug in this code?  I don't really know.
>
> Are there known problems here?
>
> I can probably get you an executable if that would help.
> ("Probably" because I haven't tried to reproduce by hand, I've only seen
> it in automation, and I'd have to do it by hand to get the exe.)
>
> Tom
>

Yes, I would appreciate if you could get me an executable, or steps to produce one.

Thanks,

Simon
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 6/7] gdb: select "Cygwin" OS ABI for Cygwin binaries

Sourceware - gdb-patches mailing list
In reply to this post by Sourceware - gdb-patches mailing list
On 3/16/20 5:08 PM, Simon Marchi via Gdb-patches wrote:

> From: Simon Marchi <[hidden email]>
>
> Before this patch, the "Windows" OS ABI is selected for all Windows
> executables, including Cygwin ones.  This patch makes GDB differentiate
> Cygwin binaries from non-Cygwin ones, and selects the "Cygwin" OS ABI
> for the Cygwin ones.
>
> To check whether a Windows PE executable is a Cygwin one, we check the
> library list in the .idata section, see if it contains "cygwin1.dll".
>
> I had to add code to parse the .idata section, because BFD doesn't seem
> to expose this information.  BFD does parse this information, but only
> to print it in textual form (function pe_print_idata):
>
>   https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=blob;f=bfd/peXXigen.c;h=e42d646552a0ca1e856e082256cd3d943b54ddf0;hb=HEAD#l1261
>
> Here's the relevant portion of the PE format documentation:
>
>   https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-idata-section
>
> This page was also useful:
>
>   https://blog.kowalczyk.info/articles/pefileformat.html#9ccef823-67e7-4372-9172-045d7b1fb006
>
> With this patch applied, this is what I get:
>
>     (gdb) file some_mingw_x86_64_binary.exe
>     Reading symbols from some_mingw_x86_64_binary.exe...
>     (gdb) show osabi
>     The current OS ABI is "auto" (currently "Windows").
>     The default OS ABI is "GNU/Linux".
>
>     (gdb) file some_mingw_i386_binary.exe
>     Reading symbols from some_mingw_i386_binary.exe...
>     (gdb) show osabi
>     The current OS ABI is "auto" (currently "Windows").
>     The default OS ABI is "GNU/Linux".
>
>     (gdb) file some_cygwin_x86_64_binary.exe
>     Reading symbols from some_cygwin_x86_64_binary.exe...
>     (gdb) show osabi
>     The current OS ABI is "auto" (currently "Cygwin").
>     The default OS ABI is "GNU/Linux".
>
> gdb/ChangeLog:
>
> * windows-tdep.h (is_linked_with_cygwin_dll): New declaration.
> * windows-tdep.c (CYGWIN_DLL_NAME): New.
> (pe_import_directory_entry): New struct type.
> (is_linked_with_cygwin_dll): New function.
> * amd64-windows-tdep.c (amd64_windows_osabi_sniffer): Select
> GDB_OSABI_CYGWIN if the BFD is linked with the Cygwin DLL.
> * i386-windows-tdep.c (i386_windows_osabi_sniffer): Likewise.
> ---
>  gdb/amd64-windows-tdep.c |   9 ++--
>  gdb/i386-windows-tdep.c  |   9 ++--
>  gdb/windows-tdep.c       | 101 +++++++++++++++++++++++++++++++++++++++
>  gdb/windows-tdep.h       |   6 +++
>  4 files changed, 119 insertions(+), 6 deletions(-)
>
> diff --git a/gdb/amd64-windows-tdep.c b/gdb/amd64-windows-tdep.c
> index 88ff794abcb6..e0346f8628fe 100644
> --- a/gdb/amd64-windows-tdep.c
> +++ b/gdb/amd64-windows-tdep.c
> @@ -1249,10 +1249,13 @@ amd64_windows_osabi_sniffer (bfd *abfd)
>  {
>    const char *target_name = bfd_get_target (abfd);
>  
> -  if (strcmp (target_name, "pei-x86-64") == 0)
> -    return GDB_OSABI_WINDOWS;
> +  if (!streq (target_name, "pei-x86-64"))
> +    return GDB_OSABI_UNKNOWN;
>  
> -  return GDB_OSABI_UNKNOWN;
> +  if (is_linked_with_cygwin_dll (abfd))
> +    return GDB_OSABI_CYGWIN;
> +
> +  return GDB_OSABI_WINDOWS;
>  }
>  
>  void _initialize_amd64_windows_tdep ();
> diff --git a/gdb/i386-windows-tdep.c b/gdb/i386-windows-tdep.c
> index a71ceda781f8..bd6107b02f1f 100644
> --- a/gdb/i386-windows-tdep.c
> +++ b/gdb/i386-windows-tdep.c
> @@ -232,10 +232,13 @@ i386_windows_osabi_sniffer (bfd *abfd)
>  {
>    const char *target_name = bfd_get_target (abfd);
>  
> -  if (strcmp (target_name, "pei-i386") == 0)
> -    return GDB_OSABI_WINDOWS;
> +  if (!streq (target_name, "pei-i386"))
> +    return GDB_OSABI_UNKNOWN;
>  
> -  return GDB_OSABI_UNKNOWN;
> +  if (is_linked_with_cygwin_dll (abfd))
> +    return GDB_OSABI_CYGWIN;
> +
> +  return GDB_OSABI_WINDOWS;
>  }
>  
>  static enum gdb_osabi
> diff --git a/gdb/windows-tdep.c b/gdb/windows-tdep.c
> index e02b1ceed387..32e551bcb175 100644
> --- a/gdb/windows-tdep.c
> +++ b/gdb/windows-tdep.c
> @@ -38,6 +38,8 @@
>  #include "libcoff.h"
>  #include "solist.h"
>  
> +#define CYGWIN_DLL_NAME "cygwin1.dll"
> +
>  /* Windows signal numbers differ between MinGW flavors and between
>     those and Cygwin.  The below enumeration was gleaned from the
>     respective headers; the ones marked with MinGW64/Cygwin are defined
> @@ -898,6 +900,105 @@ static const struct internalvar_funcs tlb_funcs =
>    NULL
>  };
>  
> +/* Layout of an element of a PE's Import Directory Table.  Based on:
> +
> +     https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-directory-table
> + */
> +
> +struct pe_import_directory_entry
> +{
> +  uint32_t import_lookup_table_rva;
> +  uint32_t timestamp;
> +  uint32_t forwarder_chain;
> +  uint32_t name_rva;
> +  uint32_t import_address_table_rva;
> +};
> +
> +gdb_static_assert (sizeof (pe_import_directory_entry) == 20);
> +
> +/* Return true if the Portable Executable behind ABFD uses the Cygwin dll
> +   (cygwin1.dll). */
> +/* See windows-tdep.h.  */
> +
> +bool
> +is_linked_with_cygwin_dll (bfd *abfd)
> +{
> +  /* The list of DLLs a PE is linked to is in the .idata section.  See:
> +
> +     https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-idata-section
> +   */
> +  asection *idata_section = bfd_get_section_by_name (abfd, ".idata");
> +  if (idata_section == nullptr)
> +    return false;
> +
> +  /* Find the virtual address of the .idata section.  We must subtract this
> +     from the RVAs (relative virtual addresses) to obtain an offset in the
> +     section. */
> +  bfd_vma idata_addr =
> +    pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_TABLE].VirtualAddress;

= on next line.  Unless it doesn't fit, then let's ignore.

> +
> +  /* Map the section's data.  */
> +  bfd_size_type idata_size;
> +  const gdb_byte *const idata_contents
> +    = gdb_bfd_map_section (idata_section, &idata_size);
> +  if (idata_contents == nullptr)
> +    {
> +      warning (_("Failed to get content of .idata section."));
> +      return false;
> +    }
> +
> +  const gdb_byte *iter = idata_contents;
> +  const gdb_byte *end = idata_contents + idata_size;
> +  const pe_import_directory_entry null_dir_entry = { 0 };
> +
> +  /* Iterate through all directory entries.  */
> +  while (true)
> +    {
> +      /* Is there enough space left in the section for another entry?  */
> +      if (iter + sizeof (pe_import_directory_entry) > end)
> + {
> +  warning (_("Failed to parse .idata section: unexpected end of "
> +     ".idata section."));
> +  break;
> + }
> +
> +      pe_import_directory_entry *dir_entry = (pe_import_directory_entry *) iter;

Is 'iter' guaranteed to be sufficiently aligned?  Recall that this is
host-independent code.

> +
> +      /* Is it the end of list marker?  */
> +      if (memcmp (dir_entry, &null_dir_entry,
> +  sizeof (pe_import_directory_entry)) == 0)
> + break;
> +
> +      bfd_vma name_addr = dir_entry->name_rva;
> +
> +      /* If the name's virtual address is smaller than the section's virtual
> +         address, there's a problem.  */
> +      if (name_addr < idata_addr
> +  || name_addr >= (idata_addr + idata_size))
> + {
> +  warning (_("\
> +Failed to parse .idata section: name's virtual address (0x%" BFD_VMA_FMT "x) \
> +is outside .idata section's range [0x%" BFD_VMA_FMT "x, 0x%" BFD_VMA_FMT "x[."),
> +   name_addr, idata_addr, idata_addr + idata_size);
> +  break;
> + }
> +
> +      const gdb_byte *name = &idata_contents[name_addr - idata_addr];
> +
> +      /* Make sure we don't overshoot the end of the section with the streq.  */
> +      if (name + sizeof(CYGWIN_DLL_NAME) > end)

Missing space before parens.

Thanks,
Pedro Alves

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 0/7] Add "Windows" OS ABI

Sourceware - gdb-patches mailing list
In reply to this post by Sourceware - gdb-patches mailing list
On 3/16/20 5:08 PM, Simon Marchi via Gdb-patches wrote:

> This patchset started out as a single patch to have the OS ABI Cygwin
> applied to Windows x86-64 binaries, here:
>
>     https://sourceware.org/legacy-ml/gdb-patches/2020-03/msg00195.html
>
> with the follow-up here:
>
>     https://sourceware.org/pipermail/gdb-patches/2020-March/000022.html
>
> Eli pointed out that it doesn't make sense for binaries compilied with
> MinGW to have the Cygwin OS ABI, that there should be separate OS ABIs
> for Cygwin and non-Cygwin Windows binaries.  This already came up in the
> following bug report:
>
>     https://sourceware.org/bugzilla/show_bug.cgi?id=21500#add_comment

Hurray.  Thanks for doing this.  Recently, another spot that could use
this was added in windows-tdep.c.  See:

  https://sourceware.org/legacy-ml/gdb-patches/2020-01/msg00048.html

Look for "bummer".

Thanks,
Pedro Alves

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 6/7] gdb: select "Cygwin" OS ABI for Cygwin binaries

Sourceware - gdb-patches mailing list
In reply to this post by Sourceware - gdb-patches mailing list
On 2020-04-01 5:36 p.m., Pedro Alves wrote:

> On 3/16/20 5:08 PM, Simon Marchi via Gdb-patches wrote:
>> +bool
>> +is_linked_with_cygwin_dll (bfd *abfd)
>> +{
>> +  /* The list of DLLs a PE is linked to is in the .idata section.  See:
>> +
>> +     https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-idata-section
>> +   */
>> +  asection *idata_section = bfd_get_section_by_name (abfd, ".idata");
>> +  if (idata_section == nullptr)
>> +    return false;
>> +
>> +  /* Find the virtual address of the .idata section.  We must subtract this
>> +     from the RVAs (relative virtual addresses) to obtain an offset in the
>> +     section. */
>> +  bfd_vma idata_addr =
>> +    pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_TABLE].VirtualAddress;
>
> = on next line.  Unless it doesn't fit, then let's ignore.

Yes it fits.

>> +
>> +  /* Map the section's data.  */
>> +  bfd_size_type idata_size;
>> +  const gdb_byte *const idata_contents
>> +    = gdb_bfd_map_section (idata_section, &idata_size);
>> +  if (idata_contents == nullptr)
>> +    {
>> +      warning (_("Failed to get content of .idata section."));
>> +      return false;
>> +    }
>> +
>> +  const gdb_byte *iter = idata_contents;
>> +  const gdb_byte *end = idata_contents + idata_size;
>> +  const pe_import_directory_entry null_dir_entry = { 0 };
>> +
>> +  /* Iterate through all directory entries.  */
>> +  while (true)
>> +    {
>> +      /* Is there enough space left in the section for another entry?  */
>> +      if (iter + sizeof (pe_import_directory_entry) > end)
>> + {
>> +  warning (_("Failed to parse .idata section: unexpected end of "
>> +     ".idata section."));
>> +  break;
>> + }
>> +
>> +      pe_import_directory_entry *dir_entry = (pe_import_directory_entry *) iter;
>
> Is 'iter' guaranteed to be sufficiently aligned?  Recall that this is
> host-independent code.

I admit I haven't thought about that.  Within the PE file, the data of sections is
aligned on at least 512 bytes.  See "FileAlignment" here:

https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#optional-header-windows-specific-fields-image-only

However, when BFD maps the file/section data in memory for GDB to read, is that mapping
guaranteed to be sufficiently aligned as well?

>> +
>> +      /* Is it the end of list marker?  */
>> +      if (memcmp (dir_entry, &null_dir_entry,
>> +  sizeof (pe_import_directory_entry)) == 0)
>> + break;
>> +
>> +      bfd_vma name_addr = dir_entry->name_rva;
>> +
>> +      /* If the name's virtual address is smaller than the section's virtual
>> +         address, there's a problem.  */
>> +      if (name_addr < idata_addr
>> +  || name_addr >= (idata_addr + idata_size))
>> + {
>> +  warning (_("\
>> +Failed to parse .idata section: name's virtual address (0x%" BFD_VMA_FMT "x) \
>> +is outside .idata section's range [0x%" BFD_VMA_FMT "x, 0x%" BFD_VMA_FMT "x[."),
>> +   name_addr, idata_addr, idata_addr + idata_size);
>> +  break;
>> + }
>> +
>> +      const gdb_byte *name = &idata_contents[name_addr - idata_addr];
>> +
>> +      /* Make sure we don't overshoot the end of the section with the streq.  */
>> +      if (name + sizeof(CYGWIN_DLL_NAME) > end)
>
> Missing space before parens.

This patch is already pushed so I've pushed the following to fix the style issues.

Thanks for the review,

Simon

From 2836752f8ff55ea1fc7f6b1e7f8ff778775646f8 Mon Sep 17 00:00:00 2001
From: Simon Marchi <[hidden email]>
Date: Wed, 1 Apr 2020 17:41:31 -0400
Subject: [PATCH] gdb: fix style issues in is_linked_with_cygwin_dll

gdb/ChangeLog:

        * windows-tdep.c (is_linked_with_cygwin_dll): Fix style.
---
 gdb/ChangeLog      | 4 ++++
 gdb/windows-tdep.c | 8 ++++----
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index d5715a8fa005..4775ff858aab 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,7 @@
+2020-04-01  Simon Marchi  <[hidden email]>
+
+ * windows-tdep.c (is_linked_with_cygwin_dll): Fix style.
+
 2020-04-01  Bernd Edlinger  <[hidden email]>

  * buildsym.c (record_line): Fix undefined behavior and preserve
diff --git a/gdb/windows-tdep.c b/gdb/windows-tdep.c
index 31b7b57005df..0042ea350e80 100644
--- a/gdb/windows-tdep.c
+++ b/gdb/windows-tdep.c
@@ -932,8 +932,8 @@ is_linked_with_cygwin_dll (bfd *abfd)
   /* Find the virtual address of the .idata section.  We must subtract this
      from the RVAs (relative virtual addresses) to obtain an offset in the
      section. */
-  bfd_vma idata_addr =
-    pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_TABLE].VirtualAddress;
+  bfd_vma idata_addr
+    = pe_data (abfd)->pe_opthdr.DataDirectory[PE_IMPORT_TABLE].VirtualAddress;

   /* Map the section's data.  */
   bfd_size_type idata_size;
@@ -984,14 +984,14 @@ is outside .idata section's range [0x%" BFD_VMA_FMT "x, 0x%" BFD_VMA_FMT "x[."),
       const gdb_byte *name = &idata_contents[name_addr - idata_addr];

       /* Make sure we don't overshoot the end of the section with the streq.  */
-      if (name + sizeof(CYGWIN_DLL_NAME) > end)
+      if (name + sizeof (CYGWIN_DLL_NAME) > end)
  continue;

       /* Finally, check if this is the dll name we are looking for.  */
       if (streq ((const char *) name, CYGWIN_DLL_NAME))
  return true;

-      iter += sizeof(pe_import_directory_entry);
+      iter += sizeof (pe_import_directory_entry);
     }

     return false;
--
2.26.0

12