Skip to content

[lldb] Detect when full DWARF debugging should be enabled #8318

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lldb/include/lldb/Target/Target.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,9 +184,9 @@ class TargetProperties : public Properties {

bool GetSwiftEnableBareSlashRegex() const;

EnableSwiftCxxInterop GetEnableSwiftCxxInterop() const;
AutoBool GetEnableSwiftCxxInterop() const;

bool GetSwiftEnableFullDwarfDebugging() const;
AutoBool GetSwiftEnableFullDwarfDebugging() const;

bool GetSwiftAllowExplicitModules() const;

Expand Down
8 changes: 4 additions & 4 deletions lldb/include/lldb/lldb-private-enumerations.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,10 @@ typedef enum SwiftModuleLoadingMode {
} SwiftModuleLoadingMode;

// BEGIN SWIFT
enum EnableSwiftCxxInterop {
eAutoDetectSwiftCxxInterop,
eEnableSwiftCxxInterop,
eDisableSwiftCxxInterop
enum class AutoBool {
Auto,
True,
False
};
// END SWIFT

Expand Down
8 changes: 4 additions & 4 deletions lldb/source/Core/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1171,16 +1171,16 @@ bool Module::IsSwiftCxxInteropEnabled() {
case eLazyBoolCalculate:
break;
}
EnableSwiftCxxInterop interop_enabled =
AutoBool interop_enabled =
Target::GetGlobalProperties().GetEnableSwiftCxxInterop();
switch (interop_enabled) {
case eEnableSwiftCxxInterop:
case AutoBool::True:
m_is_swift_cxx_interop_enabled = eLazyBoolYes;
break;
case eDisableSwiftCxxInterop:
case AutoBool::False:
m_is_swift_cxx_interop_enabled = eLazyBoolNo;
break;
case eAutoDetectSwiftCxxInterop: {
case AutoBool::Auto: {
// Look for the "-enable-experimental-cxx-interop" compile flag in the args
// of the compile units this module is composed of.
auto *sym_file = GetSymbolFile();
Expand Down
36 changes: 30 additions & 6 deletions lldb/source/Plugins/LanguageRuntime/Swift/ReflectionContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,21 @@ struct DescriptorFinderForwarder : public swift::reflection::DescriptorFinder {

std::unique_ptr<swift::reflection::BuiltinTypeDescriptorBase>
getBuiltinTypeDescriptor(const swift::reflection::TypeRef *TR) override {
if (m_descriptor_finder)
if (m_descriptor_finder && shouldConsultDescriptorFinder())

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pattern looks like it could be factored out into a template or a function that takes a std::function?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe there's a better way to do this, but I think the "obvious" template solution is more trouble than it's worth. We'd need a templated function like:

  template <typename T>
  std::unique_ptr<T>
  getDescriptor(std::function<std::unique_ptr<T>()> descriptor_func) {
    if (m_descriptor_finder && shouldConsultDescriptorFinder())
      return descriptor_func();
    return nullptr;
  }

And then on the call side we'd need something like:

  std::unique_ptr<swift::reflection::BuiltinTypeDescriptorBase>
  getBuiltinTypeDescriptor(const swift::reflection::TypeRef *TR) override {
    std::function<
        std::unique_ptr<swift::reflection::BuiltinTypeDescriptorBase>()>
        lambda =
            [&]() { return m_descriptor_finder->getBuiltinTypeDescriptor(TR); };
    return getDescriptor(lambda);
  }

We need to spell out the lambda's type because the compiler is not able to deduce them.

return m_descriptor_finder->getBuiltinTypeDescriptor(TR);
return nullptr;
}

std::unique_ptr<swift::reflection::FieldDescriptorBase>
getFieldDescriptor(const swift::reflection::TypeRef *TR) override {
if (m_descriptor_finder)
if (m_descriptor_finder && shouldConsultDescriptorFinder())
return m_descriptor_finder->getFieldDescriptor(TR);
return nullptr;
}

std::unique_ptr<swift::reflection::MultiPayloadEnumDescriptorBase>
getMultiPayloadEnumDescriptor(const swift::reflection::TypeRef *TR) override {
if (m_descriptor_finder)
if (m_descriptor_finder && shouldConsultDescriptorFinder())
return m_descriptor_finder->getMultiPayloadEnumDescriptor(TR);
return nullptr;
}
Expand All @@ -57,8 +57,26 @@ struct DescriptorFinderForwarder : public swift::reflection::DescriptorFinder {

void ClearExternalDescriptorFinder() { m_descriptor_finder = nullptr; }

void SetImageAdded(bool image_added) {
m_image_added |= image_added;
}

private:
bool shouldConsultDescriptorFinder() {
switch (Target::GetGlobalProperties().GetSwiftEnableFullDwarfDebugging()) {
case lldb_private::AutoBool::True:
return true;
case lldb_private::AutoBool::False:
return false;
case lldb_private::AutoBool::Auto:
// Full DWARF debugging is auto-enabled if there is no reflection metadata
// to read from.
return !m_image_added;
}
}

swift::reflection::DescriptorFinder *m_descriptor_finder = nullptr;
bool m_image_added = false;
};

/// An implementation of the generic ReflectionContextInterface that
Expand All @@ -82,21 +100,27 @@ class TargetReflectionContext : public ReflectionContextInterface {
swift::ReflectionSectionKind)>
find_section,
llvm::SmallVector<llvm::StringRef, 1> likely_module_names) override {
return m_reflection_ctx.addImage(find_section, likely_module_names);
auto id = m_reflection_ctx.addImage(find_section, likely_module_names);
m_forwader.SetImageAdded(id.has_value());
return id;
}

std::optional<uint32_t>
AddImage(swift::remote::RemoteAddress image_start,
llvm::SmallVector<llvm::StringRef, 1> likely_module_names) override {
return m_reflection_ctx.addImage(image_start, likely_module_names);
auto id = m_reflection_ctx.addImage(image_start, likely_module_names);
m_forwader.SetImageAdded(id.has_value());
return id;
}

std::optional<uint32_t> ReadELF(
swift::remote::RemoteAddress ImageStart,
std::optional<llvm::sys::MemoryBlock> FileBuffer,
llvm::SmallVector<llvm::StringRef, 1> likely_module_names = {}) override {
return m_reflection_ctx.readELF(ImageStart, FileBuffer,
auto id = m_reflection_ctx.readELF(ImageStart, FileBuffer,
likely_module_names);
m_forwader.SetImageAdded(id.has_value());
return id;
}

const swift::reflection::TypeRef *GetTypeRefOrNull(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,10 @@ class DWARFFieldDescriptorImpl : public swift::reflection::FieldDescriptorBase {

std::vector<std::unique_ptr<swift::reflection::FieldRecordBase>>
getFieldRecords() override {
if (!Target::GetGlobalProperties().GetSwiftEnableFullDwarfDebugging())
return {};
assert(Target::GetGlobalProperties().GetSwiftEnableFullDwarfDebugging() !=
lldb_private::AutoBool::False &&
"Full DWARF debugging for Swift is disabled!");

auto *dwarf =
llvm::dyn_cast<SymbolFileDWARF>(m_type_system.GetSymbolFile());
auto *dwarf_parser = m_type_system.GetDWARFParser();
Expand Down Expand Up @@ -303,8 +305,9 @@ class DWARFMultiPayloadEnumDescriptorImpl
std::unique_ptr<swift::reflection::BuiltinTypeDescriptorBase>
DWARFASTParserSwift::getBuiltinTypeDescriptor(
const swift::reflection::TypeRef *TR) {
if (!Target::GetGlobalProperties().GetSwiftEnableFullDwarfDebugging())
return nullptr;
assert(Target::GetGlobalProperties().GetSwiftEnableFullDwarfDebugging() !=
lldb_private::AutoBool::False &&
"Full DWARF debugging for Swift is disabled!");

auto pair = getTypeAndDie(m_swift_typesystem, TR);
if (!pair)
Expand Down Expand Up @@ -344,8 +347,9 @@ DWARFASTParserSwift::getBuiltinTypeDescriptor(
std::unique_ptr<swift::reflection::MultiPayloadEnumDescriptorBase>
DWARFASTParserSwift::getMultiPayloadEnumDescriptor(
const swift::reflection::TypeRef *TR) {
if (!Target::GetGlobalProperties().GetSwiftEnableFullDwarfDebugging())
return nullptr;
assert(Target::GetGlobalProperties().GetSwiftEnableFullDwarfDebugging() !=
lldb_private::AutoBool::False &&
"Full DWARF debugging for Swift is disabled!");

auto pair = getTypeAndDie(m_swift_typesystem, TR);
if (!pair)
Expand Down Expand Up @@ -449,8 +453,10 @@ NodePointer DWARFASTParserSwift::GetCanonicalDemangleTree(DWARFDIE &die) {

std::unique_ptr<swift::reflection::FieldDescriptorBase>
DWARFASTParserSwift::getFieldDescriptor(const swift::reflection::TypeRef *TR) {
if (!Target::GetGlobalProperties().GetSwiftEnableFullDwarfDebugging())
return nullptr;
assert(Target::GetGlobalProperties().GetSwiftEnableFullDwarfDebugging() !=
lldb_private::AutoBool::False &&
"Full DWARF debugging for Swift is disabled!");


auto pair = getTypeAndDie(m_swift_typesystem, TR);
if (!pair)
Expand Down
54 changes: 31 additions & 23 deletions lldb/source/Target/Target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3161,15 +3161,15 @@ bool Target::IsSwiftCxxInteropEnabled() {
break;
}

EnableSwiftCxxInterop interop_enabled = GetEnableSwiftCxxInterop();
AutoBool interop_enabled = GetEnableSwiftCxxInterop();
switch (interop_enabled) {
case eEnableSwiftCxxInterop:
case AutoBool::True:
m_is_swift_cxx_interop_enabled = eLazyBoolYes;
break;
case eDisableSwiftCxxInterop:
case AutoBool::False:
m_is_swift_cxx_interop_enabled = eLazyBoolNo;
break;
case eAutoDetectSwiftCxxInterop: {
case AutoBool::Auto: {
if (GetImages().IsEmpty())
m_is_swift_cxx_interop_enabled = eLazyBoolNo;
else
Expand Down Expand Up @@ -4694,10 +4694,21 @@ static constexpr OptionEnumValueElement g_memory_module_load_level_values[] = {
};

static constexpr OptionEnumValueElement g_enable_swift_cxx_interop_values[] = {
{eAutoDetectSwiftCxxInterop, "auto",
{llvm::to_underlying(AutoBool::Auto), "auto",
"Automatically detect if C++ interop mode should be enabled."},
{eEnableSwiftCxxInterop, "true", "Enable C++ interop."},
{eDisableSwiftCxxInterop, "false", "Disable C++ interop."},
{llvm::to_underlying(AutoBool::True), "true", "Enable C++ interop."},
{llvm::to_underlying(AutoBool::False), "false", "Disable C++ interop."},
};

static constexpr OptionEnumValueElement g_enable_full_dwarf_debugging[] = {
{llvm::to_underlying(AutoBool::Auto), "auto",
"Automatically detect if full DWARF debugging should be enabled. Full "
"DWARF debugging is enabled if no reflection metadata is added to the "
"debugger."},
{llvm::to_underlying(AutoBool::True), "true",
"Enable full DWARF debugging."},
{llvm::to_underlying(AutoBool::False), "false",
"Disable full DWARF debugging."},
};

#define LLDB_PROPERTIES_target
Expand Down Expand Up @@ -4925,28 +4936,25 @@ bool TargetProperties::GetSwiftEnableBareSlashRegex() const {
return true;
}

EnableSwiftCxxInterop TargetProperties::GetEnableSwiftCxxInterop() const {
AutoBool TargetProperties::GetEnableSwiftCxxInterop() const {
const uint32_t idx = ePropertySwiftEnableCxxInterop;

EnableSwiftCxxInterop enable_interop =
(EnableSwiftCxxInterop)m_experimental_properties_up->GetValueProperties()
->GetPropertyAtIndexAs<EnableSwiftCxxInterop>(idx)
.value_or(static_cast<EnableSwiftCxxInterop>(
AutoBool enable_interop =
(AutoBool)m_experimental_properties_up->GetValueProperties()
->GetPropertyAtIndexAs<AutoBool>(idx)
.value_or(static_cast<AutoBool>(
g_target_properties[idx].default_uint_value));
return enable_interop;
}

bool TargetProperties::GetSwiftEnableFullDwarfDebugging() const {
const Property *exp_property =
m_collection_sp->GetPropertyAtIndex(ePropertyExperimental);
OptionValueProperties *exp_values =
exp_property->GetValue()->GetAsProperties();
if (exp_values)
return exp_values
->GetPropertyAtIndexAs<bool>(ePropertySwiftEnableFullDwarfDebugging)
.value_or(false);

return false;
AutoBool TargetProperties::GetSwiftEnableFullDwarfDebugging() const {
const uint32_t idx = ePropertySwiftEnableCxxInterop;
AutoBool enable_dwarf_debugging =
(AutoBool)m_experimental_properties_up->GetValueProperties()
->GetPropertyAtIndexAs<AutoBool>(idx)
.value_or(static_cast<AutoBool>(
g_target_properties[idx].default_uint_value));
return enable_dwarf_debugging;
}

bool TargetProperties::GetSwiftAllowExplicitModules() const {
Expand Down
9 changes: 5 additions & 4 deletions lldb/source/Target/TargetProperties.td
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,17 @@ let Definition = "target_experimental" in {
DefaultFalse,
Desc<"Passes the -enable-bare-slash-regex compiler flag to the swift compiler.">;
def SwiftEnableCxxInterop: Property<"swift-enable-cxx-interop", "Enum">,
DefaultEnumValue<"eAutoDetectSwiftCxxInterop">,
DefaultEnumValue<"llvm::to_underlying(AutoBool::Auto)">,
EnumValues<"OptionEnumValues(g_enable_swift_cxx_interop_values)">,
Desc<"Passes the -enable-cxx-interop flag to the swift compiler.">;
def SwiftPluginServerForPath: Property<"swift-plugin-server-for-path",
"Dictionary">,
ElementType<"String">,
Desc<"A dictionary of plugin paths as keys and swift-plugin-server binaries as values">;
def SwiftEnableFullDwarfDebugging: Property<"swift-enable-full-dwarf-debugging", "Boolean">,
DefaultFalse,
Desc<"Read full debug information from DWARF for Swift debugging, whenever possible">;
def SwiftEnableFullDwarfDebugging: Property<"swift-enable-full-dwarf-debugging", "Enum">,
DefaultEnumValue<"llvm::to_underlying(AutoBool::Auto)">,
EnumValues<"OptionEnumValues(g_enable_full_dwarf_debugging)">,
Desc<"Read full debug information from DWARF for Swift debugging. By default LLDB will use DWARF debug information if it cannot use reflection metadata.">;
def SwiftAllowExplicitModules: Property<"swift-allow-explicit-modules", "Boolean">,
DefaultTrue,
Desc<"Allows explicit module flags to be passed through to ClangImporter.">;
Expand Down