Adding DWARF5 accelerator table support to llvm

Hello all,

In <https://reviews.llvm.org/D41986#977215&gt; it was brought up that
there are at least two parties interested in having DWARF5 accelerator
tables implemented, so I'm writing this email to see if there's anyone
else interested in this topic, and to try to synchronize our efforts.

Our interest for this stems from a desire to make dwarf parsing fast
on non-apple targets (specifically android). As you may know, apple
targets already use a non-standard accelerator table format, which was
a precursor to the dwarf5 one. Due to other differences in debug info
deployment model, the apple tables are not directly applicable to
other targets, so instead of trying to make them fit, we chose to go
with the standard approach.

I personally will have some time to work on this this quarter or two,
and my plan is roughly the following:
1. add .debug_names support to llvm-dwarfdump via the DebugInfo
library (to enable testing of the table generation)
2. add .debug_names generation support (not enabled by default)
3. add .debug_names support to lldb
4. validate all three things work together
5. hook up .debug_names to clang's -glldb flag.
6. add .debug_names support to lld (accelerator table merging)

Right now I have (1) roughly implemented, and I think I'll be able to
put it up for review in a couple of days (although I expect the review
will go through several revisions before being accepted). I also have
a very basic implementation of (2), but this is still quite far from
being upstreamable.

So, my question is whether anyone is planning to work, or maybe
working already on dwarf5 accelerator tables? Help with reviewing
patches would also be greatly appreciated. If you have any questions
or concerns, let me know.

regards,
Pavel

Hello, I hope I will have time to help you with that. I discussed
dwarfv5 .debug_names implementation with involved party from RH. Anyway
even if can't help much could you keep me in the loop please?

Hi Pavel,

As mentioned by Adrian in the comment you linked, I too am looking at DWARFv5
accelerator tables in LLVM.

To give you some background: my motivation is that I want to upstream support
for (Apple style) accelerator tables in llvm-dsymutil, which is currently
missing because the way they are generated is slightly different. As this
requires making changes the current code, I wanted to consider the impact on
the standard's tables. I have some old patches from Fred (Riss) that take different
approaches to this, but I have nothing concrete yet for the v5 part.

Ultimately my goal is to share as much logic as possible between the Apple and
DWARFv5 implementations, both on the reading and generation side of things.

Your timeline seems sensible. Adding support in llvm-dwarfdump will be very
useful. I look forward to reviewing this.

How do you feel about creating a [WIP] diff for (2). I'm very excited about
bundling our efforts on this. Let me know what I can do if there's anything
else I can help with.

Cheers,
Jonas

This sounds great. I would also vote for a few additions to the work:

  • modify llvm-dwarfdump or llvm-dsymutil to be able to compute and add the Apple and DWARF accelerator tables to existing object files that have DWARF in them. As we are working out the bugs we might end up with compiler bugs where not everything was added to the accelerator tables that was required. llvm-dsymutil has a “–update” option that allows it to update and re-create the Apple accelerator tables in a dSYM file. It would be nice to have this functionality so that when we pull legacy DWARF files from a build server, we have a simple way to update them with the needed indexing info so we can debug them as quickly as new DWARF files.

Within LLDB, the DWARF parser will need to abstract the indexing lookups. Right now we have each function that accesses the index doing:

if (m_using_apple_tables) {
if (m_apple_types_ap.get()) {
const char *name_cstr = name.GetCString();
m_apple_types_ap->FindByName(name_cstr, die_offsets);
}
} else {
if (!m_indexed)
Index();

m_type_index.Find(name, die_offsets);
}

We should abstract these out into a indexing base class and have one for manual DWARF indexing, one for Apple accelerator table and one for .debug_names. I look forward to seeing this in LLDB!

Greg

Some background for the benefit of everyone who may not be aware of the genesis of the DWARF v5 accelerator tables:

DWARF v5 accelerator tables are a direct evolution of the "Apple" accelerator tables that are implemented in LLVM (after going through the standardization process and being reworked/generalized there), so we hope that the implementation can at least share some common interfaces with the existing Apple accelerator table implementation where this makes sense.

-- adrian

From: Pavel Labath [mailto:labath@google.com]
Sent: Wednesday, January 17, 2018 8:14 AM
To: jdevlieghere@apple.com; LLVM Dev; LLDB; David Blaikie; Robinson, Paul
Subject: Adding DWARF5 accelerator table support to llvm

Hello all,

In <https://reviews.llvm.org/D41986#977215&gt; it was brought up that
there are at least two parties interested in having DWARF5 accelerator
tables implemented, so I'm writing this email to see if there's anyone
else interested in this topic, and to try to synchronize our efforts.

Our interest for this stems from a desire to make dwarf parsing fast
on non-apple targets (specifically android). As you may know, apple
targets already use a non-standard accelerator table format, which was
a precursor to the dwarf5 one. Due to other differences in debug info
deployment model, the apple tables are not directly applicable to
other targets, so instead of trying to make them fit, we chose to go
with the standard approach.

I personally will have some time to work on this this quarter or two,
and my plan is roughly the following:
1. add .debug_names support to llvm-dwarfdump via the DebugInfo
library (to enable testing of the table generation)
2. add .debug_names generation support (not enabled by default)
3. add .debug_names support to lldb
4. validate all three things work together
5. hook up .debug_names to clang's -glldb flag.
6. add .debug_names support to lld (accelerator table merging)

Right now I have (1) roughly implemented, and I think I'll be able to
put it up for review in a couple of days (although I expect the review
will go through several revisions before being accepted). I also have
a very basic implementation of (2), but this is still quite far from
being upstreamable.

So, my question is whether anyone is planning to work, or maybe
working already on dwarf5 accelerator tables? Help with reviewing
patches would also be greatly appreciated. If you have any questions
or concerns, let me know.

Hi Pavel,
This would not interfere/duplicate anything Sony is doing in the near
future. I think having the accelerator tables available for our
debugger team to play with would be nice, and I will certainly try to
spend some time on reviews.

FTR, next thing on the Sony list will be the new range-list/loc-list
format. We're really hoping to make `-gdwarf-5` a viable thing for
debuggers to try out by LLVM 7.0. It won't have "everything" but the
basic set of sections should be in place and be syntactically correct.

Thanks,
--paulr

FWIW I’m completely on board with everything Adrian has said in this thread :slight_smile:

-eric

Thank you for all the responses. Unfortunately I wasn't able to make
any progress on creating the patches today. I'll be sure to add
everyone who expressed interest here to the phabricator diff once I
have them ready.

Jonas, do you have any dsymutil patches I can look at? I am interested
in seeing what kind of interfaces are you using, particularly on the
reading side. I think the current DWARFAcceleratorTable interface will
need to be redesigned a bit if we want it to fit the dwarf5 tables as
well.

Thank you for all the responses. Unfortunately I wasn't able to make
any progress on creating the patches today. I'll be sure to add
everyone who expressed interest here to the phabricator diff once I
have them ready.

Jonas, do you have any dsymutil patches I can look at? I am interested
in seeing what kind of interfaces are you using, particularly on the
reading side. I think the current DWARFAcceleratorTable interface will
need to be redesigned a bit if we want it to fit the dwarf5 tables as
well.

Dsymutil never reads accelerator tables. It rebuilds them while walking the debug_info section.

Fred

Hello all,

I am looking for feedback regarding implementation of the case folding
algorithm for .debug_names hashes.

Unlike the apple tables, the .debug_names hashes are computed from
case-folded names (to enable case-insensitive lookups for languages
where that makes sense). The dwarf5 document specifies that the case
folding should be done according the the "Caseless matching" Section
of the Unicode standard (whose implementation is basically a long list
of special cases). While certainly possible, implementing this would
be much more complicated (and would probably make the code a bit
slower) than a simple tolower(3) call. And the benefits of this are
not really clear to me.

Do you know if we already make any promises or assumptions about the
encoding and/or locale of the symbol names (and here I mainly mean the
names in the debug info metadata, not llvm symbols).

If we don't already have a policy about this, then I propose to
implement the case folding via tolower() (which is compatible with the
full case folding algorithm, as long as one sticks to basic latin
characters).

What do you think?

Hello all,

I am looking for feedback regarding implementation of the case folding
algorithm for .debug_names hashes.

Unlike the apple tables, the .debug_names hashes are computed from
case-folded names (to enable case-insensitive lookups for languages
where that makes sense). The dwarf5 document specifies that the case
folding should be done according the the "Caseless matching" Section
of the Unicode standard (whose implementation is basically a long list
of special cases). While certainly possible, implementing this would
be much more complicated (and would probably make the code a bit
slower) than a simple tolower(3) call. And the benefits of this are
not really clear to me.

Assuming a UTF-8 encoding, will tolower(3) destroy any non-ASCII characters in the process? In Swift, for example, we allow a wide range of unicode characters in identifiers and I want to make sure that this doesn't cause any problems.

-- adrian

I'm not sure what it will do out-of-the-box, but I could certainly
implement it such that it does not touch the fancy characters.

However, if we already have unicode characters in the input, then it
may make sense to go all the way and implement the full folding
algorithm. Because, once we start producing hashes like this, it will
be hard to switch to being fully standard-compliant (as that would
invalidate the existing hashes).

But the question then is: can I assume the input names will be unicode
(w/utf8 encoding)?

Hello all,

I am looking for feedback regarding implementation of the case folding
algorithm for .debug_names hashes.

Unlike the apple tables, the .debug_names hashes are computed from
case-folded names (to enable case-insensitive lookups for languages
where that makes sense). The dwarf5 document specifies that the case
folding should be done according the the "Caseless matching" Section
of the Unicode standard (whose implementation is basically a long list
of special cases). While certainly possible, implementing this would
be much more complicated (and would probably make the code a bit
slower) than a simple tolower(3) call.

Most of the characters in the CaseFolding.txt file seem to be contiguous, so I think we should be able to come up with am implementation that’s relatively efficient.

And the benefits of this are not really clear to me.

Adhering to the standard is a pretty big benefit IMHO, but I know what you mean. :slight_smile:

Hello all,

I am looking for feedback regarding implementation of the case folding
algorithm for .debug_names hashes.

Unlike the apple tables, the .debug_names hashes are computed from
case-folded names (to enable case-insensitive lookups for languages
where that makes sense). The dwarf5 document specifies that the case
folding should be done according the the "Caseless matching" Section
of the Unicode standard (whose implementation is basically a long list
of special cases). While certainly possible, implementing this would
be much more complicated (and would probably make the code a bit
slower) than a simple tolower(3) call. And the benefits of this are
not really clear to me.

Assuming a UTF-8 encoding, will tolower(3) destroy any non-ASCII characters in the process? In Swift, for example, we allow a wide range of unicode characters in identifiers and I want to make sure that this doesn't cause any problems.

I'm not sure what it will do out-of-the-box, but I could certainly
implement it such that it does not touch the fancy characters.

However, if we already have unicode characters in the input, then it
may make sense to go all the way and implement the full folding
algorithm. Because, once we start producing hashes like this, it will
be hard to switch to being fully standard-compliant (as that would
invalidate the existing hashes).

But the question then is: can I assume the input names will be unicode
(w/utf8 encoding)?

We can make that happen and encode it explicitly in each compile unit:

3.1.1 Full and Partial Compilation Unit Entries
...
A DW_AT_use_UTF8 attribute, which is a flag whose presence indicates that all strings (such as the names of declared entities in the source program, or filenames in the line number table) are represented using the UTF-8 representation.

-- adrian

so I'm writing this email to see if there's anyone
else interested in this topic, and to try to synchronize our efforts.

I am sure interested in DWARF-5 .debug_names. I wrote its producer+consumer
for GDB (but not producing/using DW_IDX_DIE_offset as GDB cannot use it).

1. add .debug_names support to llvm-dwarfdump via the DebugInfo
library (to enable testing of the table generation)

FYI FSF binutils readelf can read .debug_names already for some possible
format cross-check (to prevent multiple incompatible implementations).

so I'm writing this email to see if there's anyone
else interested in this topic, and to try to synchronize our efforts.

I am sure interested in DWARF-5 .debug_names. I wrote its producer+consumer
for GDB (but not producing/using DW_IDX_DIE_offset as GDB cannot use it).

1. add .debug_names support to llvm-dwarfdump via the DebugInfo
library (to enable testing of the table generation)

FYI FSF binutils readelf can read .debug_names already for some possible
format cross-check (to prevent multiple incompatible implementations).

2. add .debug_names generation support (not enabled by default)

+

I also have a very basic implementation of (2), but this is still quite far
from being upstreamable.

Originally I expected I will reuse the GDB .debug_names producer for LLVM:
        sourceware.org Git - binutils-gdb.git/commitdiff
        sourceware.org Git - binutils-gdb.git/commitdiff

But I see you were faster.

Jan

Thanks for the heads-up. I will study these to make sure we are compatible.

Hello again,

It's been nearly six months since my first email, so it's a good time
to recap what has been done here so far. I am happy to report that
stages 1-3 (i.e. producer/consumer in llvm and integration with lldb)
of my original plan are now complete with one caveat.

The caveat is that the .debug_names section is presently not a full
drop-in replacement for the .apple_*** sections. The reason for that
is that there is no equivalent to the .apple_objc section (which links
an objc class/category name to all of its methods). I did not
implement that, because I do not see a way to embed that kind of
information to this section without some sort of an extension. Given
that this was not required for my use case, I felt it would be best to
leave this to the people working on objc support (*looks at Jonas*) to
work out the details of how to represent that.

Nonetheless, I believe that the emitted .debug_names section contains
all the data that is required by the standard, and it is sufficient to
pass all tests in the lldb integration test suite on linux (this
doesn't include objc tests). Simple benchmarks also show a large
performance improvement.I have some numbers to illustrate that
(measurements taken by using a release build of lldb to debug a debug
build of clang, clang was built with -mllvm -accel-tables=Dwarf to
enable the accelerator generation, usage of the tables was controlled
by a setting in lldb):
- setting a breakpoint on a non-existing function without the use of
accelerator tables:
real 0m5.554s
user 0m43.764s
sys 0m6.748s
(The majority of this time is spend on building a debug info index,
which is a one-shot thing. subsequent breakpoints would be fast)

- setting a breakpoint on a non-existing function with accelerator tables:
real 0m3.517s
user 0m3.136s
sys 0m0.376s
(With the index already present, we are able to quickly determine that
there is no match and finish)

- setting a breakpoint on all "dump" functions without the use of
accelerator tables:
real 0m21.544s
user 0m59.588s
sys 0m6.796s
(Apart from building the index, now we must also parse a bunch of
compile units and line tables to resolve the breakpoint locations)

- setting a breakpoint on all "dump" functions with accelerator tables:
real 0m23.644s
user 0m22.692s
sys 0m0.948s
(Here we see that this extra work is actually the bottleneck now.
Preliminary analysis shows that majority of this time is spend
inserting line table entries into the middle of a vector, which means
it should be possible to fix this with a smarter implementation).

As far as object file sizes go, in the resulting clang binary (2.3GB),
the new .debug_names section takes up about 160MB (7%), which isn't
negligible, but considering that it supersedes the
.debug_pubnames/.debug_pubtypes tables whose combined size is 490MB
(21% of the binary), switching to this table (and dropping the other
two) will have a positive impact on the binary size. Further
reductions can be made by merging the individual indexes into one
large index as a part of the link step (which will also increase
debugger speed), but it's hard to quantify the exact impact of that.

With all of this in mind, I'd like to encourage you to give the new
tables a try. All you need to do is pass -mllvm -accel-tables=Dwarf to
clang while building your project. lldb should use the generated
tables automatically. I'm particularly interested in the interop
scenario. I've checked that readelf is able to make sense of the
generated tables, but if you have any other producer/consumer of these
tables which is independent of llvm, I'd like to know whether we are
compatible with it.

I'd also like to make the new functionality more easily accessible to
users. I am not sure what our policy here is, but I was thinking of
either including this functionality in -glldb (on non-apple targets);
or by adding a separate -g flag for it (-gdebug-names-section?), with
the goal of eventual inclusion into -glldb. I exclude apple targets
because: a) they already have a thing that works and the lack of
.apple_objc would be a pessimization; b) the different debug info
distribution model means it requires more testing and code (dsymutil).
For other targets this should bring a big performance improvement when
debugging with lldb. The lack of .apple_objc will mean lldb will have
to either index the objc compile units manually, or implement a more
complicated lookup using other information in the section. However,
Objective C is not that widespread outside of apple platforms, so the
impact of this should be minimal.

What do you think?

regards,
pavel

Nice! Thanks for the update:

re: ObjC: Perhaps debug_names and .apple_objc could be emitted at the same time to address that issue at least in the short term?

As for size impact, have you tested this with fission and compressed debug info enabled? (both in terms of whether debug_names is as compressible as the pubnames/pubtypes, and whether it’s as efficient for the debugger when it is compressed? (I imagine the decompression might be expensive - maybe it’s worth keeping it decompressed, but then the relative cost may be a fair bit higher))

From: Pavel Labath [mailto:labath@google.com]
Sent: Wednesday, June 13, 2018 9:57 AM
To: jan.kratochvil@redhat.com; llvm-dev@lists.llvm.org;
jdevlieghere@apple.com; lldb-dev@lists.llvm.org; dblaikie@gmail.com;
Robinson, Paul; aprantl@apple.com; echristo@google.com;
vleschuk@accesssoftek.com; friss@apple.com
Subject: Re: [lldb-dev] Adding DWARF5 accelerator table support to llvm

Hello again,

It's been nearly six months since my first email, so it's a good time
to recap what has been done here so far. I am happy to report that
stages 1-3 (i.e. producer/consumer in llvm and integration with lldb)
of my original plan are now complete with one caveat.

The caveat is that the .debug_names section is presently not a full
drop-in replacement for the .apple_*** sections. The reason for that
is that there is no equivalent to the .apple_objc section (which links
an objc class/category name to all of its methods). I did not
implement that, because I do not see a way to embed that kind of
information to this section without some sort of an extension. Given
that this was not required for my use case, I felt it would be best to
leave this to the people working on objc support (*looks at Jonas*) to
work out the details of how to represent that.

Nonetheless, I believe that the emitted .debug_names section contains
all the data that is required by the standard, and it is sufficient to
pass all tests in the lldb integration test suite on linux (this
doesn't include objc tests). Simple benchmarks also show a large
performance improvement.I have some numbers to illustrate that
(measurements taken by using a release build of lldb to debug a debug
build of clang, clang was built with -mllvm -accel-tables=Dwarf to
enable the accelerator generation, usage of the tables was controlled
by a setting in lldb):
- setting a breakpoint on a non-existing function without the use of
accelerator tables:
real 0m5.554s
user 0m43.764s
sys 0m6.748s
(The majority of this time is spend on building a debug info index,
which is a one-shot thing. subsequent breakpoints would be fast)

- setting a breakpoint on a non-existing function with accelerator tables:
real 0m3.517s
user 0m3.136s
sys 0m0.376s
(With the index already present, we are able to quickly determine that
there is no match and finish)

- setting a breakpoint on all "dump" functions without the use of
accelerator tables:
real 0m21.544s
user 0m59.588s
sys 0m6.796s
(Apart from building the index, now we must also parse a bunch of
compile units and line tables to resolve the breakpoint locations)

- setting a breakpoint on all "dump" functions with accelerator tables:
real 0m23.644s
user 0m22.692s
sys 0m0.948s
(Here we see that this extra work is actually the bottleneck now.
Preliminary analysis shows that majority of this time is spend
inserting line table entries into the middle of a vector, which means
it should be possible to fix this with a smarter implementation).

As far as object file sizes go, in the resulting clang binary (2.3GB),
the new .debug_names section takes up about 160MB (7%), which isn't
negligible, but considering that it supersedes the
.debug_pubnames/.debug_pubtypes tables whose combined size is 490MB
(21% of the binary), switching to this table (and dropping the other
two) will have a positive impact on the binary size. Further
reductions can be made by merging the individual indexes into one
large index as a part of the link step (which will also increase
debugger speed), but it's hard to quantify the exact impact of that.

Nice.

With all of this in mind, I'd like to encourage you to give the new
tables a try. All you need to do is pass -mllvm -accel-tables=Dwarf to
clang while building your project. lldb should use the generated
tables automatically. I'm particularly interested in the interop
scenario. I've checked that readelf is able to make sense of the
generated tables, but if you have any other producer/consumer of these
tables which is independent of llvm, I'd like to know whether we are
compatible with it.

Have you tried dwarfdump (David Anderson's dumper)? If not I can
probably get somebody to experiment with it on our side.

I'd also like to make the new functionality more easily accessible to
users. I am not sure what our policy here is, but I was thinking of
either including this functionality in -glldb (on non-apple targets);
or by adding a separate -g flag for it (-gdebug-names-section?), with
the goal of eventual inclusion into -glldb. I exclude apple targets
because: a) they already have a thing that works and the lack of
.apple_objc would be a pessimization; b) the different debug info
distribution model means it requires more testing and code (dsymutil).
For other targets this should bring a big performance improvement when
debugging with lldb. The lack of .apple_objc will mean lldb will have
to either index the objc compile units manually, or implement a more
complicated lookup using other information in the section. However,
Objective C is not that widespread outside of apple platforms, so the
impact of this should be minimal.

Replacing .debug_pub{names,type} with .debug_names should also be
enabled for DWARF v5, regardless of tuning.
--paulr

Hi Pavel,

Hello again,

It's been nearly six months since my first email, so it's a good time
to recap what has been done here so far. I am happy to report that
stages 1-3 (i.e. producer/consumer in llvm and integration with lldb)
of my original plan are now complete with one caveat.

Awesome!

The caveat is that the .debug_names section is presently not a full
drop-in replacement for the .apple_*** sections. The reason for that
is that there is no equivalent to the .apple_objc section (which links
an objc class/category name to all of its methods). I did not
implement that, because I do not see a way to embed that kind of
information to this section without some sort of an extension. Given
that this was not required for my use case, I felt it would be best to
leave this to the people working on objc support (*looks at Jonas*) to
work out the details of how to represent that.

Definitely :slight_smile: I plan to start working on this (+ dsymutil support) very soon.

Nonetheless, I believe that the emitted .debug_names section contains
all the data that is required by the standard, and it is sufficient to
pass all tests in the lldb integration test suite on linux (this
doesn't include objc tests).

How did you (or do you plan to) add this (and DWARF5 in general) in the lldb test suite? It sounds like this might require a new dimension in the test matrix if we want to test all the variants with both Apple and DWARF style accelerator tables.

Simple benchmarks also show a large
performance improvement.I have some numbers to illustrate that
(measurements taken by using a release build of lldb to debug a debug
build of clang, clang was built with -mllvm -accel-tables=Dwarf to
enable the accelerator generation, usage of the tables was controlled
by a setting in lldb):
- setting a breakpoint on a non-existing function without the use of
accelerator tables:
real 0m5.554s
user 0m43.764s
sys 0m6.748s
(The majority of this time is spend on building a debug info index,
which is a one-shot thing. subsequent breakpoints would be fast)

- setting a breakpoint on a non-existing function with accelerator tables:
real 0m3.517s
user 0m3.136s
sys 0m0.376s
(With the index already present, we are able to quickly determine that
there is no match and finish)

- setting a breakpoint on all "dump" functions without the use of
accelerator tables:
real 0m21.544s
user 0m59.588s
sys 0m6.796s
(Apart from building the index, now we must also parse a bunch of
compile units and line tables to resolve the breakpoint locations)

- setting a breakpoint on all "dump" functions with accelerator tables:
real 0m23.644s
user 0m22.692s
sys 0m0.948s
(Here we see that this extra work is actually the bottleneck now.
Preliminary analysis shows that majority of this time is spend
inserting line table entries into the middle of a vector, which means
it should be possible to fix this with a smarter implementation).

As far as object file sizes go, in the resulting clang binary (2.3GB),
the new .debug_names section takes up about 160MB (7%), which isn't
negligible, but considering that it supersedes the
.debug_pubnames/.debug_pubtypes tables whose combined size is 490MB
(21% of the binary), switching to this table (and dropping the other
two) will have a positive impact on the binary size. Further
reductions can be made by merging the individual indexes into one
large index as a part of the link step (which will also increase
debugger speed), but it's hard to quantify the exact impact of that.

With all of this in mind, I'd like to encourage you to give the new
tables a try. All you need to do is pass -mllvm -accel-tables=Dwarf to
clang while building your project. lldb should use the generated
tables automatically. I'm particularly interested in the interop
scenario. I've checked that readelf is able to make sense of the
generated tables, but if you have any other producer/consumer of these
tables which is independent of llvm, I'd like to know whether we are
compatible with it.

I know of one internal consumer but it ignores the accelerator tables so I don’t expect any issues there.

I'd also like to make the new functionality more easily accessible to
users. I am not sure what our policy here is, but I was thinking of
either including this functionality in -glldb (on non-apple targets);
or by adding a separate -g flag for it (-gdebug-names-section?), with
the goal of eventual inclusion into -glldb. I exclude apple targets
because: a) they already have a thing that works and the lack of
.apple_objc would be a pessimization; b) the different debug info
distribution model means it requires more testing and code (dsymutil).

Changing the default on non-Apple targets sounds good. Once we have Objective-C support I’ll do some additional (internal) testing after which we can consider flipping the switch globally.