[RFAv3 2/6] Improve process exit status macros on MinGW

Philippe Waroquiers
2019-05-04T16:18:08Z

gdb/ChangeLog
2019-05-04 Eli Zaretskii <eliz@gnu.org>
Philippe Waroquiers <philippe.waroquiers@skynet.be>

* common/gdb_wait.h (WIFEXITED, WIFSIGNALED, WEXITSTATUS,
WTERMSIG): Define better versions for MinGW.
* windows-nat.c (xlate): Uncomment the definition.
(windows_status_to_termsig): New function.
---
gdb/common/gdb_wait.h | 27 +++++++++++++++++++++++++++
gdb/windows-nat.c | 18 ++++++++++++++----
2 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/gdb/common/gdb_wait.h b/gdb/common/gdb_wait.h
index b3b752cf3a..ca95240009 100644
--- a/gdb/common/gdb_wait.h
+++ b/gdb/common/gdb_wait.h
@@ -40,13 +40,31 @@
NOTE exception for GNU/Linux below). We also fail to declare
wait() and waitpid(). */

+/* For MINGW, the underlying idea is that when a Windows program is terminated
+ by a fatal exception, its exit code is the value of that exception, as
+ defined by the various STATUS_* symbols in the Windows API headers.
+
+ The below is not perfect, because a program could legitimately exit normally
+ with a status whose value happens to have the high bits set, but that's
+ extremely rare, to say the least, and it is deemed such a negligibly small
+ probability of false positives is justified by the utility of reporting the
+ terminating signal in the "normal" cases. */
+
#ifndef WIFEXITED
+#if defined (__MINGW32__)
+#define WIFEXITED(stat_val) (((stat_val) & 0xC0000000) == 0)
+#else
#define WIFEXITED(w) (((w)&0377) == 0)
#endif
+#endif

#ifndef WIFSIGNALED
+#if defined (__MINGW32__)
+#define WIFSIGNALED(stat_val) (((stat_val) & 0xC0000000) == 0xC0000000)
+#else
#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
#endif
+#endif

#ifndef WIFSTOPPED
#ifdef IBM6000
@@ -64,12 +82,21 @@
#endif

#ifndef WEXITSTATUS
+#if defined (__MINGW32__)
+#define WEXITSTATUS(stat_val) ((stat_val) & 255)
+#else
#define WEXITSTATUS(w) (((w) >> 8) & 0377) /* same as WRETCODE */
#endif
+#endif

#ifndef WTERMSIG
+#if defined (__MINGW32__)
+extern enum gdb_signal windows_status_to_termsig (int stat_val);
+#define WTERMSIG(stat_val) windows_status_to_termsig (stat_val)
+#else
#define WTERMSIG(w) ((w) & 0177)
#endif
+#endif

#ifndef WSTOPSIG
#define WSTOPSIG WEXITSTATUS
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index ae4e3d55b3..c90caeda6a 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -280,9 +280,9 @@ static const int *mappings;
a segment register or not. */
static segment_register_p_ftype *segment_register_p;

-/* See windows_nat_target::resume to understand why this is commented
- out. */
-#if 0
+/* See windows_nat_target::resume to understand why xlate is not used
+ to translate a signal into an exception. */
+
/* This vector maps the target's idea of an exception (extracted
from the DEBUG_EVENT structure) to GDB's idea. */

@@ -302,7 +302,17 @@ static const struct xlate_exception xlate[] =
{STATUS_FLOAT_DIVIDE_BY_ZERO, GDB_SIGNAL_FPE}
};

-#endif /* 0 */
+/* Translate a windows exception inside STAT_VAL into a gdb_signal.
+ This should only be called if WIFSIGNALED (stat_val). */
+
+enum gdb_signal
+windows_status_to_termsig (int stat_val)
+{
+ for (const xlate_exception &x : xlate)
+ if (x.them == (stat_val & ~0xC0000000))
+ return x.us;
+ return GDB_SIGNAL_UNKNOWN;
+}

struct windows_nat_target final : public x86_nat_target<inf_child_target>
{
--
2.20.1