Differences between revisions 14 and 53 (spanning 39 versions)
Revision 14 as of 2014-10-13 22:28:29
Size: 7933
Editor: PedroAlves
Comment: Add Requirements section
Revision 53 as of 2019-06-04 12:56:37
Size: 13255
Editor: PedroAlves
Comment: Cross off C++ exceptions and cleanups items
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
## page was renamed from cxx-convertion
Line 4: Line 3:
This project explores migrating GDB to C++ as implementation language. GDB is currently written in C90. This project explores migrating GDB to C++ as implementation language. --(GDB is currently written in C90.)-- --((Not anymore! GDB started requiring a C++03 compiler on 2016-09-05.)-- (Not anymore! GDB started requiring a C++11 compiler on 2016-10-28.)

= Status =

(2016/10) - GDB's master now [[https://sourceware.org/ml/gdb-patches/2016-10/msg00773.html|requires a C++11 compiler]].

(2016/09) - GDB's master now requires a C++ compiler. There's no way to revert back to C mode any longer. The {{{--disable-build-with-cxx}}} configure option has been removed.

(2016/04) - GDB's master now builds with a C++ compiler by default. To revert back to C mode, configure with {{{--disable-build-with-cxx}}}. The [[https://sourceware.org/ml/gdb/2016-04/msg00011.html|current plan]] is to start requiring C++ after the
[[https://sourceware.org/gdb/schedule/|GDB 7.12 release]] (around July/August).

(2016/04) - [[https://sourceware.org/ml/gdb-patches/2016-03/msg00351.html|GDB no longer throws from signal handlers]]

(2015/11) - [[https://sourceware.org/ml/gdb/2015-11/msg00035.html|Looking for feedback on which hosts still need conversion work]]

(2015/11) - {{{-fpermissive}}} no longer used. C++ mode builds with {{{-Werror}}} too. x86_64/Aaarch64 GNU/Linux and x86_64 MinGW ports (at least) now build cleanly in C++ mode.

(2015/03) - GDB's master now builds with a C++ compiler, albeit with many {{{-fpermissive}}} warnings still. To enable C++ mode, configure with {{{--enable-build-with-cxx}}}.

(2015/02) - Consensus among maintainers obtained. Plan marching ahead.

(2014/09) - Need to gather consensus amongst maintainers.

= Follow =

Most discussions happen on the gdb-patches list.

The tracker bug is [[https://sourceware.org/PR19105|PR19105 - GDB should be a C++ program]].
Line 37: Line 63:
A gradual move to C++ would enable us to fix these problems.

We should be reasonably conservative in our choices of C++ constructs to use. We can also see what the GCC community comes up with here -- our needs are a little different, but probably not drastically so.
A gradual move to C++ will enable us to fix these problems.

We should be reasonably conservative in our choices of C++ constructs to use. We can also see what the GCC community came up with here -- our needs are a little different, but probably not drastically so.
Line 43: Line 69:
We'd like to convert everything under src/gdb/ to C++, including GDBserver. Vectors, exceptions and cleanups are all shared between GDB and GDBserver, and all are things we would like to convert. More code will become shared as the [[Common]] and [[LocalRemoteFeatureParity]] projects progress. We're like to convert everything under src/gdb/ to C++, including GDBserver. Vectors, exceptions and cleanups are all shared between GDB and GDBserver, and all are things we would like to convert. More code will become shared as the [[Common]] and [[LocalRemoteFeatureParity]] projects progress.

Use of major C++ libraries, like glibmm, qt, boost, etc. are out of scope.
Line 51: Line 79:
= Status =

(2014/09) - Need to gather consensus amongst maintainers.
 * Keep the use case of using GDB as a library in mind. E.g., consider impact of global constructors/destructors.

= Coding conventions =

We propose following GCC's C++ coding conventions, diverging only on finer detail, as we find necessary.

See these documents, which have extensive detail:

 * [[https://gcc.gnu.org/codingconventions.html#CandCxx|GCC's C++ Language Conventions]] (scroll down a bit)

 * [[https://gcc.gnu.org/codingrationale.html|GCC Coding Conventions Rationale and Discussion]]

A point where we'll want to diverge is in permitting the use of C++ exceptions, because GDB already makes use of exceptions and RAII.
Line 57: Line 95:
 1.#0 Gather consensus amongst maintainers.

 1. Encourage new GDB contributions/patches to be valid C++.

 1. Modify GDB so it can be compiled with -Wc++-compat.

 1. Change GDB to compile with a C++ compiler (-Wc++-compat is not complete), keeping the support to build with a C compiler.

    Test on a sufficient number of hosts.

 1. Require a C++ compiler.
 1.#0 --(Gather consensus amongst maintainers.)-- Done!

 1. --(Encourage new GDB contributions/patches to be valid C++.)-- Done, first we had a buildbot, then GDB flipped to use a C++ compiler by default.

 1. --(Add a --enable-build-with-cxx option (default: no) to compile GDB with a C++ compiler, keeping the support to build with a C compiler, and use the g++ -fpermissive option.)-- Done! [[https://sourceware.org/ml/gdb-patches/2015-02/msg00202.html|gdb-patches@ post.]]

 1. --(Modify GDB so it can be compiled in C++ mode with G++'s -fpermissive option.)-- Done! [[https://sourceware.org/ml/gdb-patches/2015-02/msg00202.html|gdb-patches@ post.]]

 1. --(Split the TRY_CATCH macro into TRY/CATCH macros to better map to C++'s 'throw'/'try...catch' in C++ mode, and eliminate all the volatile gdb_exception objects.)-- Done! [[https://sourceware.org/ml/gdb-patches/2015-02/msg00202.html|gdb-patches@ post.]]

 1. --(Modify GDB so it can be compiled in C++ mode without G++'s {{{-fpermissive}}} option.)-- Done!

 1. --(Start compiling GDB with -Wc++-compat in C mode, to ensure C++ mode doesn't regress.)-- Skipped. Because this option isn't aware of templates, with the enum flags class, code like {{{flags |= FLAG_SOMETHING}}} doesn't build. We'll rely on the buildbot instead.

    Test on a sufficient number of hosts. Make sure {{{--enable-targets=all}}} builds.

 1. --(Require a C++ compiler.)-- Done!
Line 71: Line 115:
  * --(Change the exception handling system to use C++ exceptions behind the scenes.)-- Done.

    --(Reimplement throw_exception/TRY_CATCH with 'throw'/'try...catch' in C++ mode, letting cleanups co-exist while they're not completely phased out. Destructors of locals won't be called automatically until this step is done. (Note: this step may be done before a C++ compiler is required.))-- Done. [[https://sourceware.org/ml/gdb-patches/2015-02/msg00202.html|Patches posted here.]]

  * --(Stop throwing exceptions from signal handlers (and eliminate immediate_quit))-- Done.
Line 73: Line 123:
    struct breakpoint_ops, struct target_ops, struct varobj, etc.

  * Use standard containers and algorithms

    (Note GCC hasn't eliminated VEC completely, but converted it into a template; consider importing that.)

  * Change the exception handling system to use C++ exceptions.

    throw_exception/TRY_CATCH -> 'throw'/'try...catch'.

  * Convert cleanups to RAII.
    struct breakpoint_ops, --(struct target_ops)--, struct varobj, etc.

  * --(Progressively convert cleanups to RAII.)-- Done!
    (Note that the way the TRY/CATCH wrappers are crafted, RAII/destructors _can_ coexist with cleanups. There's no need for a [[https://en.wikipedia.org/wiki/Flag_day_%28computing%29|flag day]].)

  * Use standard containers and algorithms<<BR>>
    --((Note GCC hasn't eliminated VEC completely, but converted it into a template; consider importing that.))-- (Use std::vector.)

  * --(Once all cleanups are converted/eliminated, we can remove the TRY/CATCH wrappers, making all code use 'throw'/'try...catch' directly.)-- Done!
Line 105: Line 153:
Tromey has a C++ [[https://gitorious.org/binutils-gdb/pages/Home|conversion attempt branch here]]. [[https://gitorious.org/binutils-gdb/gdb/commits/000d6fc03252b4a0a39a398bddab327edc703fd8|Browse commits here]].  * Tromey had a C++ [[https://gitorious.org/binutils-gdb/pages/Home|conversion attempt branch here]], including automated scripts, which are in {{{ git@github.com:tromey/gdb-refactoring-scripts.git }}}. This wasn't complete but was a pretty decent stab at the change. Steps still missing were automating the TRY_CATCH conversion, and actually building with G++.

 * Pedro picked that up, rebased it, added a --enable-builds-with-cxx configure switch, did the TRY_CATCH conversion and many other fixes to make GDB build with either G++ or GCC on x86_64 Fedora 20. The work was split in two. A first part that made build GDB in C++ mode, with -fpermissive. That is fully merged in [[https://sourceware.org/ml/gdb-patches/2015-03/msg00194.html|mainline]] already.

The second part of the work fixes all -fpermissive errors/warnings, until GDB builds cleanly with -Werror, on x86_64 Fedora 20. This is found in this (rebasing) branch:
Line 108: Line 160:
git://gitorious.org/binutils-gdb/gdb.git tromey/cxx-conversion-attempt git@github.com:palves/gdb.git palves/cxx-conversion-attempt-part-2-no-fpermissive
Line 111: Line 163:
Much of that was done using automated scripts, which are in {{{ git@github.com:tromey/gdb-refactoring-scripts.git }}}. This isn't complete but is a pretty decent stab at the change. A step still missing is automating the TRY_CATCH conversion. [[https://github.com/palves/gdb/commits/palves/cxx-conversion-attempt-part-2-no-fpermissive|Browse commits here]].

Note: The branch passes regression tests on x86_64 Fedora 20 in C and C++ modes.

Also note that C++ mode is not the default (both branch and master). You'll need to configure with --enable-build-with-cxx.

Pedro's scripts used for the automated conversions (based on Tromey's),
[[https://github.com/palves/gdb-refactoring-scripts|are here (web version)]], or:

{{{
git@github.com:palves/gdb-refactoring-scripts.git master
}}}

This project explores migrating GDB to C++ as implementation language. GDB is currently written in C90. (Not anymore! GDB started requiring a C++03 compiler on 2016-09-05. (Not anymore! GDB started requiring a C++11 compiler on 2016-10-28.)

Status

(2016/10) - GDB's master now requires a C++11 compiler.

(2016/09) - GDB's master now requires a C++ compiler. There's no way to revert back to C mode any longer. The --disable-build-with-cxx configure option has been removed.

(2016/04) - GDB's master now builds with a C++ compiler by default. To revert back to C mode, configure with --disable-build-with-cxx. The current plan is to start requiring C++ after the GDB 7.12 release (around July/August).

(2016/04) - GDB no longer throws from signal handlers

(2015/11) - Looking for feedback on which hosts still need conversion work

(2015/11) - -fpermissive no longer used. C++ mode builds with -Werror too. x86_64/Aaarch64 GNU/Linux and x86_64 MinGW ports (at least) now build cleanly in C++ mode.

(2015/03) - GDB's master now builds with a C++ compiler, albeit with many -fpermissive warnings still. To enable C++ mode, configure with --enable-build-with-cxx.

(2015/02) - Consensus among maintainers obtained. Plan marching ahead.

(2014/09) - Need to gather consensus amongst maintainers.

Follow

Most discussions happen on the gdb-patches list.

The tracker bug is PR19105 - GDB should be a C++ program.

Rationale

The goal for moving to C++ is to make GDB more robust, easier to maintain, and to lower barriers for newcomers.

  • C++ is a standardized, well known, popular language.
  • C++ is nearly a superset of C90 used in GDB.
  • The C subset of C++ is just as efficient as C.
  • C++ supports cleaner code in several significant cases.
  • C++ makes it easier to write cleaner interfaces by making it harder to break interface boundaries.
  • C++ never requires uglier code.
  • C++ is not a panacea but it is an improvement.

GDB is already written in poor-man's C++-in-C. Examples:

  • Subclasses: struct breakpoint. struct target_ops. Several more.
  • Virtual functions. target_ops, breakpoint_ops, languages, values and more all use these.
  • Overloaded functions.
  • Templates. Both observers and VEC are templates.
  • Exceptions. Used ubiquitously.
  • RAII. Cleanups, but they are dynamic and more error-prone.
  • Global constructors -- init.c.

In most cases, GDB's implementation of these features is inferior to that of the C++ compiler. Its exceptions are slower. Its data structures have less type-safety. Both cleanups and TRY_CATCH are error-prone in practice. We have run into various situations where errors could have been prevented through the use of better type-safety -- e.g., wrapper classes for the CU- versus section-offset case.

A gradual move to C++ will enable us to fix these problems.

We should be reasonably conservative in our choices of C++ constructs to use. We can also see what the GCC community came up with here -- our needs are a little different, but probably not drastically so.

Scope

We're like to convert everything under src/gdb/ to C++, including GDBserver. Vectors, exceptions and cleanups are all shared between GDB and GDBserver, and all are things we would like to convert. More code will become shared as the Common and LocalRemoteFeatureParity projects progress.

Use of major C++ libraries, like glibmm, qt, boost, etc. are out of scope.

Requirements

  • It must be possible to build GDB with the standard C++ compiler of supported systems. E.g., for OpenBSD that means GCC 4.2.1, which in turn means only C++98/03 features can be used (and some more advanced features may not be usable either).
  • It shall still be possible to build GDB on older hardware architectures with constrained memory. E.g., 256MB might be all the compiler/linker has to work with. Make sure GDB builds with "ulimit -d 262144".
  • Keep the use case of using GDB as a library in mind. E.g., consider impact of global constructors/destructors.

Coding conventions

We propose following GCC's C++ coding conventions, diverging only on finer detail, as we find necessary.

See these documents, which have extensive detail:

A point where we'll want to diverge is in permitting the use of C++ exceptions, because GDB already makes use of exceptions and RAII.

Transition plan

  1. Gather consensus amongst maintainers. Done!

  2. Encourage new GDB contributions/patches to be valid C++. Done, first we had a buildbot, then GDB flipped to use a C++ compiler by default.

  3. Add a --enable-build-with-cxx option (default: no) to compile GDB with a C++ compiler, keeping the support to build with a C compiler, and use the g++ -fpermissive option. Done! gdb-patches@ post.

  4. Modify GDB so it can be compiled in C++ mode with G++'s -fpermissive option. Done! gdb-patches@ post.

  5. Split the TRY_CATCH macro into TRY/CATCH macros to better map to C++'s 'throw'/'try...catch' in C++ mode, and eliminate all the volatile gdb_exception objects. Done! gdb-patches@ post.

  6. Modify GDB so it can be compiled in C++ mode without G++'s -fpermissive option. Done!

  7. Start compiling GDB with -Wc++-compat in C mode, to ensure C++ mode doesn't regress. Skipped. Because this option isn't aware of templates, with the enum flags class, code like flags |= FLAG_SOMETHING doesn't build. We'll rely on the buildbot instead.

    • Test on a sufficient number of hosts. Make sure --enable-targets=all builds.

  8. Require a C++ compiler. Done!

  9. Change the codebase to use C++'s native features.
    • Change the exception handling system to use C++ exceptions behind the scenes. Done.

      • Reimplement throw_exception/TRY_CATCH with 'throw'/'try...catch' in C++ mode, letting cleanups co-exist while they're not completely phased out. Destructors of locals won't be called automatically until this step is done. (Note: this step may be done before a C++ compiler is required.) Done. Patches posted here.

    • Stop throwing exceptions from signal handlers (and eliminate immediate_quit) Done.

    • Convert C-style inheritance to true C++ inheritance
      • struct breakpoint_ops, struct target_ops, struct varobj, etc.

    • Progressively convert cleanups to RAII. Done!

      • (Note that the way the TRY/CATCH wrappers are crafted, RAII/destructors _can_ coexist with cleanups. There's no need for a flag day.)

    • Use standard containers and algorithms

      • (Note GCC hasn't eliminated VEC completely, but converted it into a template; consider importing that.) (Use std::vector.)

    • Once all cleanups are converted/eliminated, we can remove the TRY/CATCH wrappers, making all code use 'throw'/'try...catch' directly. Done!

Concerns raised, and answers

  • GDBserver (and the in-process agent) should be lean - C++ will bloat it too much.

False: see Tom's code size experimentations

Tom's experimentations with different C++ compiler options addressed this. In particular, we have the -static/-static-libstdc++/-static-libgcc options as well as --enable-sjlj-exceptions, which all should allow building a lean self-contained in-process agent (which shared code with GDBserver) that doesn't force much into the target process, as well as providing an option for deploying a self-contained, lean GDBserver for constrained/embedded environments with possibly no shared C++ runtime deployed.

  • Support for C++ exceptions is lacking on some important host/target toolchains

Android was one such example raised. C++ exceptions wasn't really supported by the Android SDK, at the time, but things may have moved on since. It is now easier to use exceptions there nowadays. See e.g., Do the Android NDK toolchain binaries build with or without exceptions by default? .

Older supported Unix hosts, particularly ones that might not have GCC available used to be a concern here, but GDB has been removing support for them anyway. E.g., IRIX and True64 are going away: GDB dropping support for mips-irix and alpha-tru64.

Plus, if we leave any such host behind, older GDB's will always be available if someone needs to debug something on them.

Resources

Branches and patches

  • Tromey had a C++ conversion attempt branch here, including automated scripts, which are in  git@github.com:tromey/gdb-refactoring-scripts.git . This wasn't complete but was a pretty decent stab at the change. Steps still missing were automating the TRY_CATCH conversion, and actually building with G++.

  • Pedro picked that up, rebased it, added a --enable-builds-with-cxx configure switch, did the TRY_CATCH conversion and many other fixes to make GDB build with either G++ or GCC on x86_64 Fedora 20. The work was split in two. A first part that made build GDB in C++ mode, with -fpermissive. That is fully merged in mainline already.

The second part of the work fixes all -fpermissive errors/warnings, until GDB builds cleanly with -Werror, on x86_64 Fedora 20. This is found in this (rebasing) branch:

git@github.com:palves/gdb.git palves/cxx-conversion-attempt-part-2-no-fpermissive

Browse commits here.

Note: The branch passes regression tests on x86_64 Fedora 20 in C and C++ modes.

Also note that C++ mode is not the default (both branch and master). You'll need to configure with --enable-build-with-cxx.

Pedro's scripts used for the automated conversions (based on Tromey's), are here (web version), or:

git@github.com:palves/gdb-refactoring-scripts.git master

Development Strategy

While conversion is essential, doing so in a manner that limits disruption is important. To that end, we suggest the following development strategy.

We should be reasonably conservative in our choices of C++ constructs to use. We can also see what the GCC community comes up with here -- our needs are a little different, but probably not drastically so.

Before implementing a change, identify the benefit. Primarily we expect the benefit to be better code adaptability, code writability, or code readibility. However, improvements to memory use, compile time, and run time are feasible.

Prefer to follow the idioms and APIs of the C++ standard library when implementing new abstractions. This approach is most important for abstractions that have equivalents in the standard, but for which using the standard abstraction is undesirable. This approach preserves maximum flexibility in implementation.

Where reasonable, implement the change behind the existing APIs. For example, replace the bodies of an existing macro or function with the new implementation. Test this configuration for both correctness and performance. Send that change as a patch.

Change the uses of the old API to the new API in bite-size patches. A patch that changes every file is more disruptive than ten patches changing ten distinct sets of files.


OngoingWork

None: cxx-conversion (last edited 2019-06-04 12:56:37 by PedroAlves)

All content (C) 2008 Free Software Foundation. For terms of use, redistribution, and modification, please see the WikiLicense page.