[2/2] Use enums for human-readable exception information.

Message ID 20200117153140.2231-2-ssbssa@yahoo.de
State New, archived
Headers

Commit Message

Terekhov, Mikhail via Gdb-patches Jan. 17, 2020, 3:31 p.m. UTC
  Changes to $_siginfo type to this:

(gdb) pt $_siginfo
type = struct EXCEPTION_RECORD {
    enum ExceptionCode ExceptionCode;
    unsigned int ExceptionFlags;
    struct EXCEPTION_RECORD *ExceptionRecord;
    void *ExceptionAddress;
    unsigned int NumberParameters;
    union {
        void *ExceptionInformation[15];
        struct {...} AccessViolationInformation;
    };
}
(gdb) pt $_siginfo.ExceptionCode
type = enum ExceptionCode {FATAL_APP_EXIT = 1073741845,
    DBG_CONTROL_C = 1073807365, DBG_CONTROL_BREAK = 1073807368,
    DATATYPE_MISALIGNMENT = 2147483650, BREAKPOINT, SINGLE_STEP,
    ACCESS_VIOLATION = 3221225477, IN_PAGE_ERROR,
    ILLEGAL_INSTRUCTION = 3221225501, NONCONTINUABLE_EXCEPTION = 3221225509,
    INVALID_DISPOSITION, ARRAY_BOUNDS_EXCEEDED = 3221225612,
    FLOAT_DENORMAL_OPERAND, FLOAT_DIVIDE_BY_ZERO, FLOAT_INEXACT_RESULT,
    FLOAT_INVALID_OPERATION, FLOAT_OVERFLOW, FLOAT_STACK_CHECK,
    FLOAT_UNDERFLOW, INTEGER_DIVIDE_BY_ZERO, INTEGER_OVERFLOW,
    PRIV_INSTRUCTION, STACK_OVERFLOW = 3221225725, FAST_FAIL = 3221226505}
(gdb) pt $_siginfo.AccessViolationInformation
type = struct {
    enum ViolationType Type;
    void *Address;
}
(gdb) pt $_siginfo.AccessViolationInformation.Type
type = enum ViolationType {READ_ACCESS_VIOLATION, WRITE_ACCESS_VIOLATION,
    DATA_EXECUTION_PREVENTION_VIOLATION = 8}

Which makes it easier to understand the reason of the exception:

(gdb) p $_siginfo
$1 = {
  ExceptionCode = ACCESS_VIOLATION,
  ExceptionFlags = 0,
  ExceptionRecord = 0x0,
  ExceptionAddress = 0x401632 <main+18>,
  NumberParameters = 2,
  {
    ExceptionInformation = {0x1, 0x123, 0x0 <repeats 13 times>},
    AccessViolationInformation = {
      Type = WRITE_ACCESS_VIOLATION,
      Address = 0x123
    }
  }
}

gdb/ChangeLog:

2020-01-17  Hannes Domani  <ssbssa@yahoo.de>

	* windows-tdep.c (struct enum_value_name): New struct.
	(create_enum): New function.
	(windows_get_siginfo_type): Create and use enum types.
---
 gdb/windows-tdep.c | 93 ++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 86 insertions(+), 7 deletions(-)
  

Comments

Simon Marchi Feb. 7, 2020, 10:02 p.m. UTC | #1
On 2020-01-17 10:31 a.m., Hannes Domani via gdb-patches wrote:
> Changes to $_siginfo type to this:
> 
> (gdb) pt $_siginfo
> type = struct EXCEPTION_RECORD {
>     enum ExceptionCode ExceptionCode;
>     unsigned int ExceptionFlags;
>     struct EXCEPTION_RECORD *ExceptionRecord;
>     void *ExceptionAddress;
>     unsigned int NumberParameters;
>     union {
>         void *ExceptionInformation[15];
>         struct {...} AccessViolationInformation;
>     };
> }
> (gdb) pt $_siginfo.ExceptionCode
> type = enum ExceptionCode {FATAL_APP_EXIT = 1073741845,
>     DBG_CONTROL_C = 1073807365, DBG_CONTROL_BREAK = 1073807368,
>     DATATYPE_MISALIGNMENT = 2147483650, BREAKPOINT, SINGLE_STEP,
>     ACCESS_VIOLATION = 3221225477, IN_PAGE_ERROR,
>     ILLEGAL_INSTRUCTION = 3221225501, NONCONTINUABLE_EXCEPTION = 3221225509,
>     INVALID_DISPOSITION, ARRAY_BOUNDS_EXCEEDED = 3221225612,
>     FLOAT_DENORMAL_OPERAND, FLOAT_DIVIDE_BY_ZERO, FLOAT_INEXACT_RESULT,
>     FLOAT_INVALID_OPERATION, FLOAT_OVERFLOW, FLOAT_STACK_CHECK,
>     FLOAT_UNDERFLOW, INTEGER_DIVIDE_BY_ZERO, INTEGER_OVERFLOW,
>     PRIV_INSTRUCTION, STACK_OVERFLOW = 3221225725, FAST_FAIL = 3221226505}
> (gdb) pt $_siginfo.AccessViolationInformation
> type = struct {
>     enum ViolationType Type;
>     void *Address;
> }
> (gdb) pt $_siginfo.AccessViolationInformation.Type
> type = enum ViolationType {READ_ACCESS_VIOLATION, WRITE_ACCESS_VIOLATION,
>     DATA_EXECUTION_PREVENTION_VIOLATION = 8}
> 
> Which makes it easier to understand the reason of the exception:
> 
> (gdb) p $_siginfo
> $1 = {
>   ExceptionCode = ACCESS_VIOLATION,
>   ExceptionFlags = 0,
>   ExceptionRecord = 0x0,
>   ExceptionAddress = 0x401632 <main+18>,
>   NumberParameters = 2,
>   {
>     ExceptionInformation = {0x1, 0x123, 0x0 <repeats 13 times>},
>     AccessViolationInformation = {
>       Type = WRITE_ACCESS_VIOLATION,
>       Address = 0x123
>     }
>   }
> }

Well, this kind of goes against the last comment I left on patch 1 (to use the
actual types found in the real structure), but I think that what you are
suggesting here is quite convenient, so I wouldn't be against doing something
like that.

Please add a bit of comments to your code to explain what you are doing.  Since
you are inventing types that don't exist in the documentation, it's not obvious
to know what this is doing.

Simon
  

Patch

diff --git a/gdb/windows-tdep.c b/gdb/windows-tdep.c
index 50efa31709..080b3a89d2 100644
--- a/gdb/windows-tdep.c
+++ b/gdb/windows-tdep.c
@@ -668,12 +668,75 @@  windows_gdb_signal_to_target (struct gdbarch *gdbarch, enum gdb_signal signal)
   return -1;
 }
 
+struct enum_value_name
+{
+  uint32_t value;
+  const char *name;
+};
+
+static struct type *
+create_enum (struct gdbarch *gdbarch, int bit, const char *name,
+	     const struct enum_value_name *values, int count)
+{
+  struct type *type;
+  int i;
+
+  type = arch_type (gdbarch, TYPE_CODE_ENUM, bit, name);
+  TYPE_NFIELDS (type) = count;
+  TYPE_FIELDS (type) = (struct field *)
+    TYPE_ZALLOC (type, sizeof (struct field) * count);
+  TYPE_UNSIGNED (type) = 1;
+
+  for (i = 0; i < count; i++)
+  {
+    TYPE_FIELD_NAME (type, i) = values[i].name;
+    SET_FIELD_ENUMVAL (TYPE_FIELD (type, i), values[i].value);
+  }
+
+  return type;
+}
+
+static const struct enum_value_name exception_values[] =
+{
+  { 0x40000015, "FATAL_APP_EXIT" },
+  { 0x40010005, "DBG_CONTROL_C" },
+  { 0x40010008, "DBG_CONTROL_BREAK" },
+  { 0x80000002, "DATATYPE_MISALIGNMENT" },
+  { 0x80000003, "BREAKPOINT" },
+  { 0x80000004, "SINGLE_STEP" },
+  { 0xC0000005, "ACCESS_VIOLATION" },
+  { 0xC0000006, "IN_PAGE_ERROR" },
+  { 0xC000001D, "ILLEGAL_INSTRUCTION" },
+  { 0xC0000025, "NONCONTINUABLE_EXCEPTION" },
+  { 0xC0000026, "INVALID_DISPOSITION" },
+  { 0xC000008C, "ARRAY_BOUNDS_EXCEEDED" },
+  { 0xC000008D, "FLOAT_DENORMAL_OPERAND" },
+  { 0xC000008E, "FLOAT_DIVIDE_BY_ZERO" },
+  { 0xC000008F, "FLOAT_INEXACT_RESULT" },
+  { 0xC0000090, "FLOAT_INVALID_OPERATION" },
+  { 0xC0000091, "FLOAT_OVERFLOW" },
+  { 0xC0000092, "FLOAT_STACK_CHECK" },
+  { 0xC0000093, "FLOAT_UNDERFLOW" },
+  { 0xC0000094, "INTEGER_DIVIDE_BY_ZERO" },
+  { 0xC0000095, "INTEGER_OVERFLOW" },
+  { 0xC0000096, "PRIV_INSTRUCTION" },
+  { 0xC00000FD, "STACK_OVERFLOW" },
+  { 0xC0000409, "FAST_FAIL" },
+};
+
+static const struct enum_value_name violation_values[] =
+{
+  { 0, "READ_ACCESS_VIOLATION" },
+  { 1, "WRITE_ACCESS_VIOLATION" },
+  { 8, "DATA_EXECUTION_PREVENTION_VIOLATION" },
+};
+
 static struct type *
 windows_get_siginfo_type (struct gdbarch *gdbarch)
 {
   struct windows_gdbarch_data *windows_gdbarch_data;
-  struct type *uint_type, *void_ptr_type;
-  struct type *siginfo_ptr_type, *siginfo_type;
+  struct type *uint_type, *void_ptr_type, *code_enum, *violation_enum;
+  struct type *violation_type, *para_type, *siginfo_ptr_type, *siginfo_type;
 
   windows_gdbarch_data = get_windows_gdbarch_data (gdbarch);
   if (windows_gdbarch_data->siginfo_type != NULL)
@@ -683,22 +746,38 @@  windows_get_siginfo_type (struct gdbarch *gdbarch)
 				 1, "unsigned int");
   void_ptr_type = lookup_pointer_type (builtin_type (gdbarch)->builtin_void);
 
+  code_enum = create_enum (gdbarch, gdbarch_int_bit (gdbarch),
+			   "ExceptionCode", exception_values,
+			   ARRAY_SIZE (exception_values));
+
+  violation_enum = create_enum (gdbarch, gdbarch_ptr_bit (gdbarch),
+				"ViolationType", violation_values,
+				ARRAY_SIZE (violation_values));
+
+  violation_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT);
+  append_composite_type_field (violation_type, "Type", violation_enum);
+  append_composite_type_field (violation_type, "Address", void_ptr_type);
+
+  para_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_UNION);
+  append_composite_type_field (para_type, "ExceptionInformation",
+			       lookup_array_range_type (void_ptr_type, 0, 14));
+  append_composite_type_field (para_type, "AccessViolationInformation",
+			       violation_type);
+
   siginfo_type = arch_composite_type (gdbarch, "EXCEPTION_RECORD",
 				      TYPE_CODE_STRUCT);
   siginfo_ptr_type = arch_pointer_type (gdbarch, gdbarch_ptr_bit (gdbarch),
 					NULL, siginfo_type);
 
-  append_composite_type_field (siginfo_type, "ExceptionCode", uint_type);
+  append_composite_type_field (siginfo_type, "ExceptionCode", code_enum);
   append_composite_type_field (siginfo_type, "ExceptionFlags", uint_type);
   append_composite_type_field (siginfo_type, "ExceptionRecord",
 			       siginfo_ptr_type);
   append_composite_type_field (siginfo_type, "ExceptionAddress",
 			       void_ptr_type);
   append_composite_type_field (siginfo_type, "NumberParameters", uint_type);
-  append_composite_type_field_aligned (siginfo_type, "ExceptionInformation",
-				       lookup_array_range_type (void_ptr_type,
-								0, 14),
-				       TYPE_LENGTH (void_ptr_type));
+  append_composite_type_field_aligned (siginfo_type, "",
+				       para_type, TYPE_LENGTH (void_ptr_type));
 
   windows_gdbarch_data->siginfo_type = siginfo_type;