Skip to content

Commit cb57578

Browse files
authored
[llvm-debuginfo-analyzer] Support DW_TAG_module (#137228)
- Adds support for `DW_TAG_module` DIEs and recurse over their children. Prior to this patch, entities hanging below `DW_TAG_module` were just not visible. This DIE kind is commonly generated by Objective-C modules. This patch will represent such entities, which will print as ``` [001] {CompileUnit} '/llvm/tools/clang/test/modules/<stdin>' [002] {Producer} 'LLVM version 3.7.0' {Directory} '/llvm/tools/clang/test/modules' {File} '<stdin>' [002] {Module} 'DebugModule' ``` The minimal test case included is just the result of ``` $ llc llvm/test/DebugInfo/X86/DIModule.ll -accel-tables=Dwarf -o llvm/unittests/DebugInfo/LogicalView/Inputs/test-dwarf-clang-module.o -filetype=obj ```
1 parent f37c241 commit cb57578

File tree

9 files changed

+64
-1
lines changed

9 files changed

+64
-1
lines changed

llvm/docs/CommandGuide/llvm-debuginfo-analyzer.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -489,8 +489,8 @@ The given criteria describes the debug line state machine registers.
489489
=Discriminator: Line that has a discriminator.
490490
=EndSequence: Marks the end in the sequence of lines.
491491
=EpilogueBegin: Marks the start of a function epilogue.
492-
=LineDebug: Lines that correspond to debug lines.
493492
=LineAssembler: Lines that correspond to disassembly text.
493+
=LineDebug: Lines that correspond to debug lines.
494494
=NeverStepInto: marks a never step into.
495495
=NewStatement: Marks a new statement.
496496
=PrologueEnd: Marks the end of a function prologue.
@@ -519,6 +519,7 @@ The following options allow printing of scopes that match the given <kind>.
519519
=InlinedFunction: An inlined function.
520520
=Label: A label.
521521
=LexicalBlock: A lexical block.
522+
=Module: A module.
522523
=Namespace: A namespace.
523524
=Root: The element representing the main scope.
524525
=Structure: A structure.

llvm/include/llvm/DebugInfo/LogicalView/Core/LVElement.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ enum class LVSubclassID : unsigned char {
4242
LV_SCOPE_FUNCTION,
4343
LV_SCOPE_FUNCTION_INLINED,
4444
LV_SCOPE_FUNCTION_TYPE,
45+
LV_SCOPE_MODULE,
4546
LV_SCOPE_NAMESPACE,
4647
LV_SCOPE_ROOT,
4748
LV_SCOPE_TEMPLATE_PACK,

llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ class LVReader {
104104
LV_OBJECT_ALLOCATOR(ScopeFunction)
105105
LV_OBJECT_ALLOCATOR(ScopeFunctionInlined)
106106
LV_OBJECT_ALLOCATOR(ScopeFunctionType)
107+
LV_OBJECT_ALLOCATOR(ScopeModule)
107108
LV_OBJECT_ALLOCATOR(ScopeNamespace)
108109
LV_OBJECT_ALLOCATOR(ScopeRoot)
109110
LV_OBJECT_ALLOCATOR(ScopeTemplatePack)
@@ -210,6 +211,7 @@ class LVReader {
210211
LV_CREATE_OBJECT(ScopeFunction)
211212
LV_CREATE_OBJECT(ScopeFunctionInlined)
212213
LV_CREATE_OBJECT(ScopeFunctionType)
214+
LV_CREATE_OBJECT(ScopeModule)
213215
LV_CREATE_OBJECT(ScopeNamespace)
214216
LV_CREATE_OBJECT(ScopeRoot)
215217
LV_CREATE_OBJECT(ScopeTemplatePack)

llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ enum class LVScopeKind {
4848
IsLabel,
4949
IsLexicalBlock,
5050
IsMember,
51+
IsModule,
5152
IsNamespace,
5253
IsRoot,
5354
IsStructure,
@@ -181,6 +182,7 @@ class LVScope : public LVElement {
181182
KIND(LVScopeKind, IsTemplatePack);
182183
KIND_1(LVScopeKind, IsTryBlock, IsBlock);
183184
KIND_1(LVScopeKind, IsUnion, IsAggregate);
185+
KIND_2(LVScopeKind, IsModule, CanHaveRanges, CanHaveLines);
184186

185187
PROPERTY(Property, HasDiscriminator);
186188
PROPERTY(Property, CanHaveRanges);
@@ -748,6 +750,23 @@ class LVScopeFunctionType final : public LVScopeFunction {
748750
void resolveExtra() override;
749751
};
750752

753+
// Class to represent a DWARF Module.
754+
class LVScopeModule final : public LVScope {
755+
public:
756+
LVScopeModule() : LVScope() {
757+
setIsModule();
758+
setIsLexicalBlock();
759+
}
760+
LVScopeModule(const LVScopeModule &) = delete;
761+
LVScopeModule &operator=(const LVScopeModule &) = delete;
762+
~LVScopeModule() = default;
763+
764+
// Returns true if current scope is logically equal to the given 'Scope'.
765+
bool equals(const LVScope *Scope) const override;
766+
767+
void printExtra(raw_ostream &OS, bool Full = true) const override;
768+
};
769+
751770
// Class to represent a DWARF Namespace.
752771
class LVScopeNamespace final : public LVScope {
753772
LVScope *Reference = nullptr; // Reference to DW_AT_extension attribute.

llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const char *const KindEnumeration = "Enumeration";
3434
const char *const KindFile = "File";
3535
const char *const KindFunction = "Function";
3636
const char *const KindInlinedFunction = "InlinedFunction";
37+
const char *const KindModule = "Module";
3738
const char *const KindNamespace = "Namespace";
3839
const char *const KindStruct = "Struct";
3940
const char *const KindTemplateAlias = "TemplateAlias";
@@ -50,6 +51,8 @@ const char *LVScope::kind() const {
5051
const char *Kind = KindUndefined;
5152
if (getIsArray())
5253
Kind = KindArray;
54+
else if (getIsModule())
55+
Kind = KindModule;
5356
else if (getIsBlock())
5457
Kind = KindBlock;
5558
else if (getIsCallSite())
@@ -94,6 +97,7 @@ LVScopeDispatch LVScope::Dispatch = {
9497
{LVScopeKind::IsInlinedFunction, &LVScope::getIsInlinedFunction},
9598
{LVScopeKind::IsLabel, &LVScope::getIsLabel},
9699
{LVScopeKind::IsLexicalBlock, &LVScope::getIsLexicalBlock},
100+
{LVScopeKind::IsModule, &LVScope::getIsModule},
97101
{LVScopeKind::IsNamespace, &LVScope::getIsNamespace},
98102
{LVScopeKind::IsRoot, &LVScope::getIsRoot},
99103
{LVScopeKind::IsStructure, &LVScope::getIsStructure},
@@ -1962,6 +1966,18 @@ void LVScopeFunctionType::resolveExtra() {
19621966
setName(Name);
19631967
}
19641968

1969+
//===----------------------------------------------------------------------===//
1970+
// DWARF module (DW_TAG_module).
1971+
//===----------------------------------------------------------------------===//
1972+
bool LVScopeModule::equals(const LVScope *Scope) const {
1973+
// For lexical blocks, LVScope::equals() compares the parent scope.
1974+
return LVScope::equals(Scope) && (Scope->getName() == getName());
1975+
}
1976+
1977+
void LVScopeModule::printExtra(raw_ostream &OS, bool Full) const {
1978+
OS << formattedKind(kind()) << " " << formattedName(getName()) << "\n";
1979+
}
1980+
19651981
//===----------------------------------------------------------------------===//
19661982
// DWARF namespace (DW_TAG_namespace).
19671983
//===----------------------------------------------------------------------===//

llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,9 @@ LVElement *LVDWARFReader::createElement(dwarf::Tag Tag) {
233233
case dwarf::DW_TAG_GNU_template_parameter_pack:
234234
CurrentScope = createScopeTemplatePack();
235235
return CurrentScope;
236+
case dwarf::DW_TAG_module:
237+
CurrentScope = createScopeModule();
238+
return CurrentScope;
236239
default:
237240
// Collect TAGs not implemented.
238241
if (options().getInternalTag() && Tag)

llvm/tools/llvm-debuginfo-analyzer/Options.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ cl::list<LVScopeKind> cmdline::SelectScopes(
354354
clEnumValN(LVScopeKind::IsLabel, "Label", "Label."),
355355
clEnumValN(LVScopeKind::IsLexicalBlock, "LexicalBlock",
356356
"Lexical block."),
357+
clEnumValN(LVScopeKind::IsModule, "Module", "Module."),
357358
clEnumValN(LVScopeKind::IsNamespace, "Namespace", "Namespace."),
358359
clEnumValN(LVScopeKind::IsRoot, "Root", "Root."),
359360
clEnumValN(LVScopeKind::IsStructure, "Structure", "Structure."),

llvm/unittests/DebugInfo/LogicalView/DWARFReaderTest.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const char *DwarfClang = "test-dwarf-clang.o";
3333
// Two compile units: one declares `extern int foo_printf(const char *, ...);`
3434
// and another one that defines the function.
3535
const char *DwarfClangUnspecParams = "test-dwarf-clang-unspec-params.elf";
36+
const char *DwarfClangModule = "test-dwarf-clang-module.o";
3637
const char *DwarfGcc = "test-dwarf-gcc.o";
3738

3839
// Helper function to get the first compile unit.
@@ -157,6 +158,22 @@ void checkUnspecifiedParameters(LVReader *Reader) {
157158
true);
158159
}
159160

161+
// Check the basic properties on parsed DW_TAG_module.
162+
void checkScopeModule(LVReader *Reader) {
163+
LVScopeRoot *Root = Reader->getScopesRoot();
164+
LVScopeCompileUnit *CompileUnit = getFirstCompileUnit(Root);
165+
166+
EXPECT_EQ(Root->getFileFormatName(), "Mach-O 64-bit x86-64");
167+
EXPECT_EQ(Root->getName(), DwarfClangModule);
168+
169+
ASSERT_NE(CompileUnit->getChildren(), nullptr);
170+
LVElement *FirstChild = *(CompileUnit->getChildren()->begin());
171+
EXPECT_EQ(FirstChild->getIsScope(), 1);
172+
LVScopeModule *Module = static_cast<LVScopeModule *>(FirstChild);
173+
EXPECT_EQ(Module->getIsModule(), 1);
174+
EXPECT_EQ(Module->getName(), "DebugModule");
175+
}
176+
160177
// Check the logical elements selection.
161178
void checkElementSelection(LVReader *Reader) {
162179
LVScopeRoot *Root = Reader->getScopesRoot();
@@ -301,6 +318,9 @@ void elementProperties(SmallString<128> &InputsDir) {
301318

302319
Reader = createReader(ReaderHandler, InputsDir, DwarfClangUnspecParams);
303320
checkUnspecifiedParameters(Reader.get());
321+
322+
Reader = createReader(ReaderHandler, InputsDir, DwarfClangModule);
323+
checkScopeModule(Reader.get());
304324
}
305325

306326
// Logical elements selection.
Binary file not shown.

0 commit comments

Comments
 (0)