RFC: Removing the legacy debug mode from libc++

The debug mode goes back to the early days of libc++; unfortunately, several important issues were discovered with its original design along the way because of which further development was effectively abandoned. The debug mode is currently in a legacy state and not actively maintained; some vendors, including Apple, never shipped it.

Most of the issues with the design stem from the decision to have a global database for storing debug information:

  • All accesses to the database require taking a global lock, adding a significant performance penalty;
  • The debug mode is not usable in a constexpr context;
  • The initial goal of the debug mode was to be ABI compatible with the normal library. Unfortunately, this doesn’t work since the state of the global database needs to be updated consistently throughout the whole application, which means that it is effectively ABI affecting. This was discovered when we noticed actual runtime issues while mixing components built with different settings for the debug mode.

For these reasons, the legacy debug mode has been a maintenance burden for a while, but this became especially noticeable due to the recent work on hardening in libc++. There is a fair amount of conceptual overlap between the new hardening modes and the legacy debug mode, and having the two coexist ends up being confusing, particularly for users of the library trying to figure out which settings need to be turned on to enable the hardening mode. We propose to simply remove the legacy debug mode from libc++, to be replaced by the new hardening modes (including the new debug mode).

As for the timeline, we would:

  1. Switch the default for enabling debug mode support in the shared library from ON to OFF in LLVM 17.
  2. Have a release note and a deprecation warning for vendors and users when the debug mode is enabled in LLVM 17.
  3. Remove support for the legacy debug mode in LLVM 18.
1 Like

I support this, however since this is a potentially breaking change (see below), I think it would be nice to get the attention of a few other vendors on this.

Pinging some folks to get some attention: @sylvestre @mgorny @rnk @thakis @petrhosek @EricWF
If it gets to a review, we can also ping the usual libc++ vendors group there.

This is a breaking change because we’d be removing the symbols that implement the global database. Anyone relying on those right now would get linker errors when the removal is complete. However, as it is explained above, this legacy debug mode is effectively already broken so I would argue that anyone relying on it must not be relying on it in production.

I really like the proposal. It would be good to have something better than our current solution.

Is there a reason for not giving users a 2 releases transition period?

We don’t think there are many users relying on it because it’s already broken, and we’d like to be able to reuse some of the names associated to the debug mode sooner than in ~1 year.

cc @hansw2000

I think it makes complete sense to remove the legacy debug mode. So far as I’m aware, Google only ever tried to use _LIBCPP_DEBUG level 1, and that has been completely replaced with the hardening mode, which has been great.

Let me take a moment to thank the libc++ community for that feature! Chrome is very interested in minimizing C++ library UB, and this was a major improvement.

I think you would be justified in removing the old debug mode sooner than later. Maybe you could make some backwards compatibility compromises, like providing stubs for the symbols exposed in past shared library versions. There is a large space of reasonable solutions.

1 Like

When it makes it easier to implement the new hardening in libc++ I’ve no objection against a faster removal.

Update: it turns out we already switched the default for debug mode support to OFF a year ago (⚙ D122941 [libc++] Make the Debug mode a configuration-time only option and ⚙ D127360 [libc++] Drop the legacy debug mode symbols by default). To the best of my knowledge, we didn’t receive any complaints.

I think this allows us to significantly speed up the timeline and remove the legacy debug mode for the upcoming LLVM 17 release. This is great for hardening work because it saves us from distinguishing between the “legacy” and the “new” debug mode and just reuse the obvious name.

Please let us know if there are any objections to removing the legacy debug mode in the upcoming release. The fact that there were no complaints about the previous changes seems to indicate lack of usage.

Update: the patch to remove the legacy debug mode has been merged to main and will be a part of the upcoming LLVM 17 release (as long as it sticks).