-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[llvm-dwarfdump] Support for DW_AT_language_name and DW_AT_language_version #162449
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
base: main
Are you sure you want to change the base?
[llvm-dwarfdump] Support for DW_AT_language_name and DW_AT_language_version #162449
Conversation
@llvm/pr-subscribers-llvm-binary-utilities @llvm/pr-subscribers-debuginfo Author: Michael Buch (Michael137) ChangesDepends on:
Makes sure we dump the attributes in a user-friendly way. More info on the attributes here: https://dwarfstd.org/languages-v6.html Full diff: https://github.com/llvm/llvm-project/pull/162449.diff 7 Files Affected:
diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def
index 2c9a3c0f6fb04..fbf22cc6f760b 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.def
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.def
@@ -424,6 +424,9 @@ HANDLE_DW_AT(0x89, export_symbols, 5, DWARF)
HANDLE_DW_AT(0x8a, deleted, 5, DWARF)
HANDLE_DW_AT(0x8b, defaulted, 5, DWARF)
HANDLE_DW_AT(0x8c, loclists_base, 5, DWARF)
+// New in Dwarf v6:
+HANDLE_DW_AT(0x90, language_name, 6, DWARF)
+HANDLE_DW_AT(0x91, language_version, 6, DWARF)
// Vendor extensions:
HANDLE_DW_AT(0x806, GHS_namespace_alias, 0, GHS)
diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.h b/llvm/include/llvm/BinaryFormat/Dwarf.h
index 2c5012510a5c3..ba74ab9515a75 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.h
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.h
@@ -997,6 +997,7 @@ LLVM_ABI StringRef VisibilityString(unsigned Visibility);
LLVM_ABI StringRef VirtualityString(unsigned Virtuality);
LLVM_ABI StringRef EnumKindString(unsigned EnumKind);
LLVM_ABI StringRef LanguageString(unsigned Language);
+LLVM_ABI StringRef SourceLanguageNameString(SourceLanguageName Lang);
LLVM_ABI StringRef CaseString(unsigned Case);
LLVM_ABI StringRef ConventionString(unsigned Convention);
LLVM_ABI StringRef InlineCodeString(unsigned Code);
@@ -1038,6 +1039,7 @@ LLVM_ABI unsigned getSubOperationEncoding(unsigned OpEncoding,
LLVM_ABI unsigned getVirtuality(StringRef VirtualityString);
LLVM_ABI unsigned getEnumKind(StringRef EnumKindString);
LLVM_ABI unsigned getLanguage(StringRef LanguageString);
+LLVM_ABI unsigned getSourceLanguageName(StringRef SourceLanguageNameString);
LLVM_ABI unsigned getCallingConvention(StringRef LanguageString);
LLVM_ABI unsigned getAttributeEncoding(StringRef EncodingString);
LLVM_ABI unsigned getMacinfo(StringRef MacinfoString);
diff --git a/llvm/lib/BinaryFormat/Dwarf.cpp b/llvm/lib/BinaryFormat/Dwarf.cpp
index 8b24044e19e50..033c6a44be638 100644
--- a/llvm/lib/BinaryFormat/Dwarf.cpp
+++ b/llvm/lib/BinaryFormat/Dwarf.cpp
@@ -472,6 +472,26 @@ StringRef llvm::dwarf::LanguageDescription(dwarf::SourceLanguageName lname) {
return "Unknown";
}
+llvm::StringRef llvm::dwarf::SourceLanguageNameString(SourceLanguageName Lang) {
+ switch (Lang) {
+#define HANDLE_DW_LNAME(ID, NAME, DESC, LOWER_BOUND) \
+ case DW_LNAME_##NAME: \
+ return "DW_LNAME_" #NAME;
+#include "llvm/BinaryFormat/Dwarf.def"
+ }
+
+ return {};
+}
+
+unsigned
+llvm::dwarf::getSourceLanguageName(StringRef SourceLanguageNameString) {
+ return StringSwitch<unsigned>(SourceLanguageNameString)
+#define HANDLE_DW_LNAME(ID, NAME, DESC, LOWER_BOUND) \
+ .Case("DW_LNAME_" #NAME, DW_LNAME_##NAME)
+#include "llvm/BinaryFormat/Dwarf.def"
+ .Default(0);
+}
+
StringRef llvm::dwarf::CaseString(unsigned Case) {
switch (Case) {
case DW_ID_case_sensitive:
@@ -762,6 +782,8 @@ StringRef llvm::dwarf::AttributeValueString(uint16_t Attr, unsigned Val) {
return DefaultedMemberString(Val);
case DW_AT_APPLE_enum_kind:
return EnumKindString(Val);
+ case DW_AT_language_name:
+ return SourceLanguageNameString(static_cast<SourceLanguageName>(Val));
}
return StringRef();
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
index edc69a36cdff2..212a0c039298b 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -149,7 +149,8 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
if (!Name.empty())
WithColor(OS, Color) << Name;
else if (Attr == DW_AT_decl_line || Attr == DW_AT_decl_column ||
- Attr == DW_AT_call_line || Attr == DW_AT_call_column) {
+ Attr == DW_AT_call_line || Attr == DW_AT_call_column ||
+ Attr == DW_AT_language_version) {
if (std::optional<uint64_t> Val = FormValue.getAsUnsignedConstant())
OS << *Val;
else
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_name.s b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_name.s
new file mode 100644
index 0000000000000..af581753be56a
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_name.s
@@ -0,0 +1,35 @@
+# Demonstrate dumping DW_AT_language_name.
+# RUN: llvm-mc -triple=x86_64--linux -filetype=obj < %s | \
+# RUN: llvm-dwarfdump -v - | FileCheck %s
+
+# CHECK: .debug_abbrev contents:
+# CHECK: DW_AT_language_name DW_FORM_data2
+# CHECK: DW_AT_language_name DW_FORM_data2
+# CHECK: .debug_info contents:
+# CHECK: DW_AT_language_name [DW_FORM_data2] (DW_LNAME_C)
+# CHECK: DW_AT_language_name [DW_FORM_data2] (0x0000)
+
+ .section .debug_abbrev,"",@progbits
+ .byte 1 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_no
+ .ascii "\220\001" # DW_AT_language_name
+ .byte 5 # DW_FORM_data2
+ .ascii "\220\001" # DW_AT_language_name
+ .byte 5 # DW_FORM_data2
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+
+ .section .debug_info,"",@progbits
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # Unit type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 1 # Abbrev [1] DW_TAG_compile_unit
+ .short 3 # DW_AT_language_name
+ .short 0 # DW_AT_language_name
+ .byte 0
+.Ldebug_info_end0:
diff --git a/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version.s b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version.s
new file mode 100644
index 0000000000000..f1be8fdf6cd3e
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/DW_AT_language_version.s
@@ -0,0 +1,35 @@
+# Demonstrate dumping DW_AT_language_version.
+# RUN: llvm-mc -triple=x86_64--linux -filetype=obj < %s | \
+# RUN: llvm-dwarfdump -v - | FileCheck %s
+
+# CHECK: .debug_abbrev contents:
+# CHECK: DW_AT_language_version DW_FORM_data4
+# CHECK: DW_AT_language_version DW_FORM_data2
+# CHECK: .debug_info contents:
+# CHECK: DW_AT_language_version [DW_FORM_data4] (201402)
+# CHECK: DW_AT_language_version [DW_FORM_data2] (0)
+
+ .section .debug_abbrev,"",@progbits
+ .byte 1 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_no
+ .ascii "\221\001" # DW_AT_language_version
+ .byte 6 # DW_FORM_data4
+ .ascii "\221\001" # DW_AT_language_version
+ .byte 5 # DW_FORM_data2
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+
+ .section .debug_info,"",@progbits
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 5 # DWARF version number
+ .byte 1 # Unit type
+ .byte 8 # Address Size (in bytes)
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 1 # Abbrev [1] DW_TAG_compile_unit
+ .long 201402 # DW_AT_language_version
+ .short 0 # DW_AT_language_version
+ .byte 0
+.Ldebug_info_end0:
diff --git a/llvm/unittests/BinaryFormat/DwarfTest.cpp b/llvm/unittests/BinaryFormat/DwarfTest.cpp
index 684e59fa2785c..1162eb709aa83 100644
--- a/llvm/unittests/BinaryFormat/DwarfTest.cpp
+++ b/llvm/unittests/BinaryFormat/DwarfTest.cpp
@@ -219,4 +219,39 @@ TEST(DwarfTest, lname) {
EXPECT_EQ(roundtrip(DW_LANG_##NAME), DW_LANG_##NAME);
#include "llvm/BinaryFormat/Dwarf.def"
}
+
+TEST(DwarfTest, lname_getSourceLanguageName) {
+ // Some basics.
+ EXPECT_EQ(getSourceLanguageName("DW_LNAME_Ada"), DW_LNAME_Ada);
+ EXPECT_EQ(getSourceLanguageName("DW_LNAME_Metal"), DW_LNAME_Metal);
+
+ // Test invalid input.
+ EXPECT_EQ(getSourceLanguageName(""), 0U);
+ EXPECT_EQ(getSourceLanguageName("blah"), 0U);
+ EXPECT_EQ(getSourceLanguageName("DW_LNAME__something_unlikely"), 0U);
+ EXPECT_EQ(getSourceLanguageName("DW_LANG_C"), 0U);
+
+ // Test that we cover all DW_LNAME_ names.
+#define xstr(X) #X
+#define HANDLE_DW_LNAME(ID, NAME, DESC, LOWER_BOUND) \
+ EXPECT_EQ(getSourceLanguageName(xstr(DW_LNAME_##NAME)), DW_LNAME_##NAME);
+#include "llvm/BinaryFormat/Dwarf.def"
+}
+
+TEST(DwarfTest, lname_SourceLanguageNameString) {
+ // Some basics.
+ EXPECT_EQ(SourceLanguageNameString(DW_LNAME_C_plus_plus),
+ "DW_LNAME_C_plus_plus");
+ EXPECT_EQ(SourceLanguageNameString(DW_LNAME_CPP_for_OpenCL),
+ "DW_LNAME_CPP_for_OpenCL");
+
+ // Test invalid input.
+ EXPECT_EQ(SourceLanguageNameString(static_cast<SourceLanguageName>(0)), "");
+
+ // Test that we cover all DW_LNAME_ names.
+#define xstr(X) #X
+#define HANDLE_DW_LNAME(ID, NAME, DESC, LOWER_BOUND) \
+ EXPECT_EQ(SourceLanguageNameString(DW_LNAME_##NAME), xstr(DW_LNAME_##NAME));
+#include "llvm/BinaryFormat/Dwarf.def"
+}
} // end namespace
|
…ersion Makes sure we dump the attributes in a user-friendly way.
754ef1f
to
e03b759
Compare
# CHECK: DW_AT_language_version DW_FORM_data4 | ||
# CHECK: DW_AT_language_version DW_FORM_data2 | ||
# CHECK: .debug_info contents: | ||
# CHECK: DW_AT_language_version [DW_FORM_data4] (201402) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should dwarfdump also translate this into the human-readable version?
i.e.:
dwarfdump: DW_AT_language_version (C++17)
dwarfdump -v: DW_AT_language_version (201402)
Depends on:
Makes sure we dump the attributes in a user-friendly way.
More info on the attributes here: https://dwarfstd.org/languages-v6.html