[RFC,0/5] Catch rethrow exception slicing

Message ID 20221025111945.23886-1-tdevries@suse.de
Headers
Series Catch rethrow exception slicing |

Message

Tom de Vries Oct. 25, 2022, 11:19 a.m. UTC
  I ran into a problem of object slicing of exceptions, and found another one
by grepping, and fixed them:
- commit b2829fcf9b5 ("[gdb] Fix rethrow exception slicing in
  insert_bp_location")
- commit 0a9c805dfd0 ("[gdb] Fix rethrow exception slicing in
  pretty_print_insn")

The problem of object slicing of exceptions, or exception slicing, is that a
gdb_exception_error is thrown, caught and rethrown, but the rethrow throws a
gdb_exception instead, which will not be caught by an encapsulating catch
gdb_exception_error.

I wondered if we could do something in gdb to catch these.

I came up with replacing:
...
  catch (const gdb_exception &VAR)
    {
      BODY;
    }
...
with:
...
  catch (const gdb_exception_error &VAR)
    {
      BODY;
    }
  catch (const gdb_exception_quit &VAR)
    {
      BODY;
    }
  catch (const gdb_exception &)
    {
      /* Exception slicing occurred.  */
      gdb_assert (0);
   }
...
and replacing:
...
  catch (const gdb_exception_error &VAR)
    {
      BODY;
    }
...
with:
...
  catch (const gdb_exception_error &VAR)
    {
      BODY;
    }
  catch (const gdb_exception_quit &)
    {
      throw;
    }
  catch (const gdb_exception &)
    {
      /* Exception slicing occurred.  */
      gdb_assert (0);
    }
...

Rather than doing the transformation as above, which makes things rather
verbose, I've added convenience macros CATCH_ERROR_QUIT and CATCH_ERROR, which
will make thing shorter, like this:
...
  CATCH_ERROR_QUIT (VAR, {
      BODY;
    }
...
and:
...
  CATCH_ERROR (VAR, {
      BODY;
    }
...

Note that I chose the formatting in such a way that:
- it avoids reindenting of BODY, and
- my editor does not suggest any auto-formatting changes.

This has to be done at many source locations, so I wrote a refactoring
script for it.

After the refactoring, this no longer has any matches:
...
$ find gdb* -type f | xargs grep "catch (const gdb_exception &[^)]"
$
...

This has some matches:
...
$ find gdb* -type f | xargs grep "catch (const gdb_exception &)" | wc -l
8
...

Note that we're not interested in "catch (const gdb_exception &)", because in
this case a rethrow using "throw;" cannot cause exception slicing.

OTOH, there could be other ways in which a gdb_exception is thrown than
exception slicing, so to catch those as well we'd need to transform all catch
statements.

Also, there's still "catch (gdb_exception &VAR)", though not that many:
...
$ find gdb* -type f | xargs grep "catch (gdb_exception &[^)]" | wc -l
17
...
I haven't looked into these yet.

Tested on x86_64-linux, and I didn't run into any assert.

Tom de Vries (5):
  [gdb] Catch gdb_exception_quit in munmap_list::~munmap_list
  [gdbsupport] Add CATCH_ERROR and CATCH_ERROR_QUIT
  [gdb/contrib] Add refactor.py
  [gdb/contrib] Add refactor_gdb_exception.py
  [gdb] Do refactor_gdb_exception refactoring

 gdb/aarch64-linux-tdep.c                      |   5 +-
 gdb/aarch64-tdep.c                            |  10 +-
 gdb/ada-lang.c                                |  39 ++---
 gdb/ada-typeprint.c                           |   5 +-
 gdb/amd64-tdep.c                              |  15 +-
 gdb/arch-utils.c                              |   3 +-
 gdb/break-catch-throw.c                       |  15 +-
 gdb/breakpoint.c                              |  59 +++----
 gdb/btrace.c                                  |  33 ++--
 gdb/c-varobj.c                                |  19 +--
 gdb/cli/cli-cmds.c                            |  10 +-
 gdb/cli/cli-script.c                          |   5 +-
 gdb/compile/compile-c-symbols.c               |  15 +-
 gdb/compile/compile-cplus-symbols.c           |  10 +-
 gdb/compile/compile-object-load.c             |   5 +-
 gdb/compile/compile-object-run.c              |   5 +-
 gdb/completer.c                               |  24 ++-
 gdb/contrib/refactor.py                       |  61 ++++++++
 gdb/contrib/refactor_gdb_exception.py         |  68 ++++++++
 gdb/corelow.c                                 |  10 +-
 gdb/cp-abi.c                                  |  10 +-
 gdb/cp-support.c                              |  14 +-
 gdb/cp-valprint.c                             |  10 +-
 gdb/darwin-nat.c                              |  10 +-
 gdb/disasm-selftests.c                        |   5 +-
 gdb/dtrace-probe.c                            |   4 +-
 gdb/dwarf2/frame-tailcall.c                   |   5 +-
 gdb/dwarf2/frame.c                            |  15 +-
 gdb/dwarf2/index-cache.c                      |  10 +-
 gdb/dwarf2/index-write.c                      |   5 +-
 gdb/dwarf2/loc.c                              |  15 +-
 gdb/dwarf2/read.c                             |   5 +-
 gdb/elf-none-tdep.c                           |   5 +-
 gdb/eval.c                                    |  24 ++-
 gdb/event-top.c                               |   9 +-
 gdb/exec.c                                    |   5 +-
 gdb/f-valprint.c                              |   5 +-
 gdb/fbsd-tdep.c                               |  20 +--
 gdb/frame-unwind.c                            |   5 +-
 gdb/frame.c                                   |  35 ++---
 gdb/gdb_bfd.c                                 |   5 +-
 gdb/gdbtypes.c                                |   5 +-
 gdb/gnu-v3-abi.c                              |   5 +-
 gdb/guile/guile-internal.h                    |   5 +-
 gdb/guile/scm-block.c                         |   5 +-
 gdb/guile/scm-breakpoint.c                    |  40 ++---
 gdb/guile/scm-cmd.c                           |   5 +-
 gdb/guile/scm-disasm.c                        |   5 +-
 gdb/guile/scm-frame.c                         |  95 +++++-------
 gdb/guile/scm-lazy-string.c                   |   5 +-
 gdb/guile/scm-math.c                          |   5 +-
 gdb/guile/scm-param.c                         |  10 +-
 gdb/guile/scm-ports.c                         |  10 +-
 gdb/guile/scm-pretty-print.c                  |   4 +-
 gdb/guile/scm-symbol.c                        |  25 ++-
 gdb/guile/scm-symtab.c                        |   5 +-
 gdb/guile/scm-type.c                          |  59 +++----
 gdb/guile/scm-value.c                         |  74 ++++-----
 gdb/i386-linux-tdep.c                         |   5 +-
 gdb/i386-tdep.c                               |  15 +-
 gdb/inf-loop.c                                |   5 +-
 gdb/infcmd.c                                  |  10 +-
 gdb/inferior.h                                |   5 +-
 gdb/infrun.c                                  |  29 ++--
 gdb/jit.c                                     |   5 +-
 gdb/language.c                                |   5 +-
 gdb/linespec.c                                |  19 +--
 gdb/linux-fork.c                              |   5 +-
 gdb/linux-nat.c                               |  20 +--
 gdb/linux-tdep.c                              |   5 +-
 gdb/linux-thread-db.c                         |  20 +--
 gdb/main.c                                    |  20 +--
 gdb/maint-test-options.c                      |   5 +-
 gdb/mi/mi-cmd-break.c                         |   5 +-
 gdb/mi/mi-cmd-stack.c                         |   5 +-
 gdb/mi/mi-interp.c                            |   5 +-
 gdb/mi/mi-main.c                              |  10 +-
 gdb/objc-lang.c                               |   5 +-
 gdb/p-valprint.c                              |   5 +-
 gdb/parse.c                                   |  10 +-
 gdb/printcmd.c                                |  20 +--
 gdb/python/py-arch.c                          |   5 +-
 gdb/python/py-breakpoint.c                    |  35 ++---
 gdb/python/py-cmd.c                           |   5 +-
 gdb/python/py-connection.c                    |   5 +-
 gdb/python/py-finishbreakpoint.c              |  30 ++--
 gdb/python/py-frame.c                         | 100 +++++-------
 gdb/python/py-framefilter.c                   |  10 +-
 gdb/python/py-gdb-readline.c                  |   5 +-
 gdb/python/py-inferior.c                      |  15 +-
 gdb/python/py-infthread.c                     |  15 +-
 gdb/python/py-lazy-string.c                   |   5 +-
 gdb/python/py-linetable.c                     |   5 +-
 gdb/python/py-objfile.c                       |  20 +--
 gdb/python/py-param.c                         |   5 +-
 gdb/python/py-prettyprint.c                   |   9 +-
 gdb/python/py-progspace.c                     |  10 +-
 gdb/python/py-record-btrace.c                 |  20 +--
 gdb/python/py-record.c                        |  10 +-
 gdb/python/py-symbol.c                        |  40 ++---
 gdb/python/py-tui.c                           |   5 +-
 gdb/python/py-type.c                          |  94 +++++-------
 gdb/python/py-unwind.c                        |  20 +--
 gdb/python/py-utils.c                         |   5 +-
 gdb/python/py-value.c                         | 145 +++++++-----------
 gdb/python/python.c                           |  43 ++----
 gdb/record-btrace.c                           |  40 ++---
 gdb/record-full.c                             |  20 +--
 gdb/regcache.c                                |   5 +-
 gdb/remote-fileio.c                           |   5 +-
 gdb/remote.c                                  |  25 ++-
 gdb/riscv-tdep.c                              |  10 +-
 gdb/rs6000-aix-tdep.c                         |   5 +-
 gdb/rs6000-tdep.c                             |  10 +-
 gdb/rust-lang.c                               |   5 +-
 gdb/rust-parse.c                              |  10 +-
 gdb/s390-tdep.c                               |   5 +-
 gdb/solib-dsbt.c                              |   4 +-
 gdb/solib-frv.c                               |   4 +-
 gdb/solib-svr4.c                              |  39 ++---
 gdb/solib.c                                   |  20 +--
 gdb/source-cache.c                            |   5 +-
 gdb/sparc64-linux-tdep.c                      |   5 +-
 gdb/stack.c                                   |  58 +++----
 gdb/symfile-mem.c                             |   5 +-
 gdb/symmisc.c                                 |   5 +-
 gdb/target.c                                  |   5 +-
 gdb/thread.c                                  |  10 +-
 gdb/top.c                                     |  20 +--
 gdb/tracefile-tfile.c                         |   5 +-
 gdb/tui/tui-disasm.c                          |   5 +-
 gdb/tui/tui-io.c                              |   5 +-
 gdb/tui/tui.c                                 |   5 +-
 gdb/typeprint.c                               |   4 +-
 gdb/unittests/cli-utils-selftests.c           |   5 +-
 gdb/unittests/gdb_tilde_expand-selftests.c    |   5 +-
 gdb/unittests/gmp-utils-selftests.c           |   5 +-
 .../parse-connection-spec-selftests.c         |   5 +-
 gdb/valops.c                                  |   9 +-
 gdb/valprint.c                                |   5 +-
 gdb/value.c                                   |  10 +-
 gdb/varobj.c                                  |  29 ++--
 gdb/windows-nat.c                             |  10 +-
 gdb/x86-linux-nat.c                           |   5 +-
 gdbserver/gdbreplay.cc                        |   5 +-
 gdbserver/linux-low.cc                        |  10 +-
 gdbserver/server.cc                           |  30 ++--
 gdbsupport/common-exceptions.h                |  31 ++++
 gdbsupport/selftest.cc                        |   5 +-
 149 files changed, 1044 insertions(+), 1367 deletions(-)
 create mode 100755 gdb/contrib/refactor.py
 create mode 100644 gdb/contrib/refactor_gdb_exception.py


base-commit: 47e2c30aacff6c50a2557c86cc00f411b750805b