Debug sections contain a large amount of data. In order not to bloat the size
of the final binary, we remove them and instead emit STABS symbols for
dsymutil and the debugger to locate their contents in the object files.
With this diff, dsymutil is able to locate the debug info. However, we need
a few more features before lldb is able to work well with our binaries --
e.g. having LC_DYSYMTAB accurately reflect the number of local symbols,
emitting LC_UUID, and more. Those will be handled in follow-up diffs.
Note also that the STABS we emit differ slightly from what ld64 does. First, we
emit the path to the source file as one N_SO symbol instead of two. (ld64
emits one N_SO for the dirname and one of the basename.) Second, we do not
emit N_BNSYM and N_ENSYM STABS to mark the start and end of functions,
because the N_FUN STABS already serve that purpose. @clayborg recommended
these changes based on his knowledge of what the debugging tools look for.
Additionally, this current implementation doesn't accurately reflect the size
of function symbols. It uses the size of their containing sectioins as a proxy,
but that is only accurate if .subsections_with_symbols is set, and if there
isn't an N_ALT_ENTRY in that particular subsection. I think we have two
options to solve this:
- We can split up subsections by symbol even if .subsections_with_symbols is not set, but include constraints to ensure those subsections retain their order in the final output. This is ld64's approach.
- We could just add a size field to our Symbol class. This seems simpler, and I'm more inclined toward it, but I'm not sure if there are use cases that it doesn't handle well. As such I'm punting on the decision for now.