Differences between revisions 11 and 12
Revision 11 as of 2014-10-10 17:10:08
Size: 7311
Editor: PedroAlves
Comment:
Revision 12 as of 2014-10-11 12:25:11
Size: 7428
Editor: PedroAlves
Comment: Clarify scope regarding GDBserver
Deletions are marked like this. Additions are marked like this.
Line 43: Line 43:
We'd like to convert everything under src/gdb/ to C++, including GDBserver. Vectors, exceptions, cleanups, these are all shared between  GDB and GDBserver. We'd like to convert everything under src/gdb/ to C++.

We'd like to convert
GDBserver too. Vectors, exceptions, cleanups, these are all shared between GDB and GDBserver, and as [[Common]] and [[LocalRemoteFeatureParity]] projects progress, more and more will be shared.

This project explores migrating GDB to C++ as implementation language. GDB is currently written in C90.

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++ 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.

Scope

We'd like to convert everything under src/gdb/ to C++.

We'd like to convert GDBserver too. Vectors, exceptions, cleanups, these are all shared between GDB and GDBserver, and as Common and LocalRemoteFeatureParity projects progress, more and more will be shared.

Status

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

Transition plan

  1. Gather consensus amongst maintainers.
  2. Encourage new GDB contributions/patches to be valid C++.
  3. Modify GDB so it can be compiled with -Wc++-compat.
  4. 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.
  5. Require a C++ compiler.
  6. Change the codebase to use C++'s native features.
    • Convert C-style inheritance to true C++ inheritance
      • 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.

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 has a C++ conversion attempt branch here. Browse commits here.

git://gitorious.org/binutils-gdb/gdb.git tromey/cxx-conversion-attempt

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.

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.