[lld-macho] Emit STABS symbols for debugging, and drop debug sections
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:
1. 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.
2. 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.
Reviewed By: clayborg
Differential Revision: https://reviews.llvm.org/D89257
2020-12-02 06:45:01 +08:00
|
|
|
//===- DWARF.cpp ----------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "Dwarf.h"
|
|
|
|
#include "InputFiles.h"
|
|
|
|
#include "InputSection.h"
|
|
|
|
#include "OutputSegment.h"
|
|
|
|
|
|
|
|
#include <memory>
|
|
|
|
|
|
|
|
using namespace lld;
|
|
|
|
using namespace lld::macho;
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
std::unique_ptr<DwarfObject> DwarfObject::create(ObjFile *obj) {
|
|
|
|
auto dObj = std::make_unique<DwarfObject>();
|
|
|
|
bool hasDwarfInfo = false;
|
2022-06-22 04:40:27 +08:00
|
|
|
// LLD only needs to extract the source file path and line numbers from the
|
|
|
|
// debug info, so we initialize DwarfObject with just the sections necessary
|
|
|
|
// to get that path. The debugger will locate the debug info via the object
|
|
|
|
// file paths that we emit in our STABS symbols, so we don't need to process &
|
|
|
|
// emit them ourselves.
|
2021-03-10 13:41:34 +08:00
|
|
|
for (const InputSection *isec : obj->debugSections) {
|
2021-04-28 03:22:44 +08:00
|
|
|
if (StringRef *s =
|
2021-07-02 08:33:55 +08:00
|
|
|
StringSwitch<StringRef *>(isec->getName())
|
2021-04-28 03:22:44 +08:00
|
|
|
.Case(section_names::debugInfo, &dObj->infoSection.Data)
|
2022-06-22 04:40:27 +08:00
|
|
|
.Case(section_names::debugLine, &dObj->lineSection.Data)
|
2022-07-26 18:06:39 +08:00
|
|
|
.Case(section_names::debugStrOffs, &dObj->strOffsSection.Data)
|
2021-04-28 03:22:44 +08:00
|
|
|
.Case(section_names::debugAbbrev, &dObj->abbrevSection)
|
|
|
|
.Case(section_names::debugStr, &dObj->strSection)
|
|
|
|
.Default(nullptr)) {
|
2020-12-09 09:47:19 +08:00
|
|
|
*s = toStringRef(isec->data);
|
|
|
|
hasDwarfInfo = true;
|
[lld-macho] Emit STABS symbols for debugging, and drop debug sections
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:
1. 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.
2. 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.
Reviewed By: clayborg
Differential Revision: https://reviews.llvm.org/D89257
2020-12-02 06:45:01 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hasDwarfInfo)
|
|
|
|
return dObj;
|
|
|
|
return nullptr;
|
|
|
|
}
|