zequanwu created this revision.
zequanwu added reviewers: labath, martong, rnk.
Herald added a subscriber: rnkovacs.
Herald added a project: All.
zequanwu requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.

When a record type doesn't have complete type debug info, forcefully complete it
to make clang not crashing at places calling `CXXRecordDecl::data()`.

Here's an example when a class has incomplete type debug info.

  0x17AB1 | LF_CLASS [size = 48] `v8::Data`
            unique name: `.?AVData@v8@@`
            vtable: <no type>, base list: <no type>, field list: <no type>
            options: forward ref (= 0x17AB1) | has unique name, sizeof 0


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D134066

Files:
  lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
  lldb/test/Shell/SymbolFile/NativePDB/missing-type.s

Index: lldb/test/Shell/SymbolFile/NativePDB/missing-type.s
===================================================================
--- lldb/test/Shell/SymbolFile/NativePDB/missing-type.s
+++ lldb/test/Shell/SymbolFile/NativePDB/missing-type.s
@@ -1,14 +1,18 @@
 # clang-format off
 # REQUIRES: lld, x86
 
-# Test when type index is missing in FieldList.
+# Test when class type is incomplete or type index is missing in FieldList.
 # RUN: llvm-mc -triple=x86_64-windows-msvc --filetype=obj %s > %t.obj
-# RUN: lld-link /debug:full /nodefaultlib /entry:main %t.obj /out:%t.exe /base:0x140000000
-# RUN: lldb-test symbols --find=type --name=S %t.exe | FileCheck %s
+# RUN: lld-link /debug:full /nodefaultlib /entry:main %t.obj /out:%t.exe
+# RUN: lldb-test symbols --find=type --name=S %t.exe | FileCheck %s --check-prefix=MISSING-DATA-TYPE
+# RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -o "expr a" -o "exit" \
+# RUN:     | FileCheck %s --check-prefix=IMCOMPLETE-CLASS
 
-# CHECK:      name = "S", size = 4, compiler_type = {{.*}} struct S {
-# CHECK-NEXT: }
+# MISSING-DATA-TYPE:      name = "S", size = 4, compiler_type = {{.*}} struct S {
+# MISSING-DATA-TYPE-NEXT: }
 
+# IMCOMPLETE-CLASS:      (lldb) expr a
+# IMCOMPLETE-CLASS-NEXT: (A) $0 = {}
 
 
 	.text
@@ -43,10 +47,54 @@
 .Lfunc_end0:
 	.seh_endproc
                                         # -- End function
-	.section	.drectve,"yn"
-.Ltmp25:
+	.bss
+	.globl	"?a@@3VA@@A"                    # @"?a@@3VA@@A"
+	.p2align	2, 0x0
+"?a@@3VA@@A":
+	.zero	4
+	.section	.debug$S,"dr"
+	.p2align	2, 0x0
+	.long	4                               # Debug section magic
+	.long	241
+	.long	.Ltmp3-.Ltmp2                   # Subsection size
+.Ltmp2:
+	.short	.Ltmp3-.Ltmp6                   # Record length
+.Ltmp6:
+	.short	4412                            # Record kind: S_COMPILE3
+	.long	1                               # Flags and language
+	.short	208                             # CPUType
+	.short	16                              # Frontend version
+	.short	0
+	.short	0
+	.short	0
+	.short	16000                           # Backend version
+	.short	0
+	.short	0
+	.short	0
+	.asciz	"clang version 16.0.0"          # Null-terminated compiler version string
+	.p2align	2, 0x0
+.Ltmp3:
+	.p2align	2, 0x0
+	.long	241                             # Symbol subsection for main
+	.long   0
+	.p2align	2, 0x0
+	.cv_linetable	0, main, .Lfunc_end0
+	.long	241                             # Symbol subsection for globals
+	.long	.Ltmp19-.Ltmp14                 # Subsection size
+.Ltmp14:
+	.short	.Ltmp19-.Ltmp16                 # Record length
+.Ltmp16:
+	.short	4365                            # Record kind: S_GDATA32
+	.long	4103                            # Type
+	.secrel32	"?a@@3VA@@A"                # DataOffset
+	.secidx	"?a@@3VA@@A"                    # Segment
+	.asciz	"a"                             # Name
+	.p2align	2, 0x0
+
+.Ltmp19:
+	.p2align	2, 0x0
 	.section	.debug$T,"dr"
-	.p2align	2
+	.p2align	2, 0x0
 	.long	4                               # Debug section magic
 	# Pointer (0x1000)
 	.short	0xa                             # Record length
@@ -87,6 +135,7 @@
 	.short	0x0                             # SizeOf
 	.asciz	"S"                             # Name
 	.asciz	".?AUS@@"                       # LinkageName
+	# Test when a class member has missing type info.
 	# FieldList (0x1005)
 	.short	0xe                             # Record length
 	.short	0x1203                          # Record kind: LF_FIELDLIST
@@ -106,3 +155,15 @@
 	.short	0x4                             # SizeOf
 	.asciz	"S"                             # Name
 	.asciz	".?AUS@@"                       # LinkageName
+	# Test when class doesn't have full type info (forward reference to itself).
+    # Class (0x1007)
+	.short	0x1e                            # Record length
+	.short	0x1504                          # Record kind: LF_CLASS
+	.short	0x1                             # MemberCount
+	.short	0x280                           # Properties ( ForwardReference (0x80) | HasUniqueName (0x200) )
+	.long	0x0                             # FieldList: <field list>
+	.long	0x0                             # DerivedFrom
+	.long	0x0                             # VShape
+	.short	0x0                             # SizeOf
+	.asciz	"A"                             # Name
+	.asciz	".?AVA@@"                       # LinkageName
Index: lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
+++ lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
@@ -666,9 +666,21 @@
   cvt = m_index.tpi().getType(best_ti.index);
   lldbassert(IsTagRecord(cvt));
 
+  CompilerType ct = ToCompilerType(tag_qt);
   if (IsForwardRefUdt(cvt)) {
     // If we can't find a full decl for this forward ref anywhere in the debug
-    // info, then we have no way to complete it.
+    // info, then we have no way to complete it, just forcefully marking it as
+    // completed. Otherwise, clang will crash due to missing DefinitionData when
+    // trying to import AST.
+    if (!ct.GetCompleteType()) {
+      bool started = TypeSystemClang::StartTagDeclarationDefinition(ct);
+      lldbassert(started && "Unable to start a class type definition.");
+      TypeSystemClang::CompleteTagDeclarationDefinition(ct);
+      if (TypeSystemClang::IsCXXClassType(ct)) {
+        auto &ts = llvm::cast<TypeSystemClang>(*ct.GetTypeSystem());
+        ts.GetMetadata(&tag)->SetIsForcefullyCompleted();
+      }
+    }
     return false;
   }
 
@@ -683,7 +695,6 @@
 
   // Visit all members of this class, then perform any finalization necessary
   // to complete the class.
-  CompilerType ct = ToCompilerType(tag_qt);
   UdtRecordCompleter completer(best_ti, ct, tag, *this, m_index,
                                m_cxx_record_map);
   llvm::Error error =
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to