[Lldb-commits] [lldb] d671002 - [LLDB][NativePDB] Fix several crashes when parsing debug info.

Zequan Wu via lldb-commits lldb-commits at lists.llvm.org
Wed Jun 8 16:41:30 PDT 2022


Author: Zequan Wu
Date: 2022-06-08T16:41:23-07:00
New Revision: d6710023e396aa55f92e3906755d68b06489d95f

URL: https://github.com/llvm/llvm-project/commit/d6710023e396aa55f92e3906755d68b06489d95f
DIFF: https://github.com/llvm/llvm-project/commit/d6710023e396aa55f92e3906755d68b06489d95f.diff

LOG: [LLDB][NativePDB] Fix several crashes when parsing debug info.
1. If array element type is a tag decl, complete it.
2. Fix few places where `asTag` should be used instead of `asClass()`.
3. Handle the case that `PdbAstBuilder::CreateFunctionDecl` return nullptr mainly due to an existing workaround (`m_cxx_record_map`).
4. `FindMembersSize` should never return error as this would cause early exiting in `CVTypeVisitor::visitFieldListMemberStream` and then cause assertion failure.
5. In some pdbs from C++ runtime libraries have S_LPROC32 followed directly by S_LOCAL and the local variable location is a S_DEFRANGE_FRAMEPOINTER_REL. There is no information about base frame register in this case, ignoring it by returning RegisterId::NONE.
6. Add a TODO when S_DEFRANGE_SUBFIELD_REGISTER describes the variable location of a pointer type. For now, just ignoring it if the variable is pointer.

Added: 
    

Modified: 
    lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
    lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
index 80d51ab656f4a..0217186cf87a3 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
@@ -711,6 +711,10 @@ bool PdbAstBuilder::CompleteType(clang::QualType qt) {
   if (qt.isNull())
     return false;
   clang::TagDecl *tag = qt->getAsTagDecl();
+  if (qt->isArrayType()) {
+    const clang::Type *element_type = qt->getArrayElementTypeNoTypeQual();
+    tag = element_type->getAsTagDecl();
+  }
   if (!tag)
     return false;
 
@@ -1089,6 +1093,7 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id,
                                     ->getCanonicalTypeInternal();
     lldb::opaque_compiler_type_t parent_opaque_ty =
         ToCompilerType(parent_qt).GetOpaqueQualType();
+    // FIXME: Remove this workaround.
     auto iter = m_cxx_record_map.find(parent_opaque_ty);
     if (iter != m_cxx_record_map.end()) {
       if (iter->getSecond().contains({func_name, func_ct})) {
@@ -1103,18 +1108,17 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id,
     TypeIndex class_index = func_record.getClassType();
 
     CVType parent_cvt = m_index.tpi().getType(class_index);
-    ClassRecord class_record = CVTagRecord::create(parent_cvt).asClass();
+    TagRecord tag_record = CVTagRecord::create(parent_cvt).asTag();
     // If it's a forward reference, try to get the real TypeIndex.
-    if (class_record.isForwardRef()) {
+    if (tag_record.isForwardRef()) {
       llvm::Expected<TypeIndex> eti =
           m_index.tpi().findFullDeclForForwardRef(class_index);
       if (eti) {
-        class_record =
-            CVTagRecord::create(m_index.tpi().getType(*eti)).asClass();
+        tag_record = CVTagRecord::create(m_index.tpi().getType(*eti)).asTag();
       }
     }
-    if (!class_record.FieldList.isSimple()) {
-      CVType field_list = m_index.tpi().getType(class_record.FieldList);
+    if (!tag_record.FieldList.isSimple()) {
+      CVType field_list = m_index.tpi().getType(tag_record.FieldList);
       CreateMethodDecl process(m_index, m_clang, func_ti, function_decl,
                                parent_opaque_ty, func_name, func_ct);
       if (llvm::Error err = visitMemberRecordStream(field_list.data(), process))
@@ -1156,6 +1160,8 @@ PdbAstBuilder::GetOrCreateInlinedFunctionDecl(PdbCompilandSymId inlinesite_id) {
     return llvm::dyn_cast<clang::FunctionDecl>(decl);
   clang::FunctionDecl *function_decl =
       CreateFunctionDeclFromId(func_id, inlinesite_id);
+  if (function_decl == nullptr)
+    return nullptr;
 
   // Use inline site id in m_decl_to_status because it's expected to be a
   // PdbCompilandSymId so that we can parse local variables info after it.
@@ -1261,6 +1267,8 @@ PdbAstBuilder::GetOrCreateFunctionDecl(PdbCompilandSymId func_id) {
   clang::FunctionDecl *function_decl =
       CreateFunctionDecl(func_id, proc_name, proc.FunctionType, func_ct,
                          func_type->getNumParams(), storage, false, parent);
+  if (function_decl == nullptr)
+    return nullptr;
 
   lldbassert(m_uid_to_decl.count(toOpaqueUid(func_id)) == 0);
   m_uid_to_decl[toOpaqueUid(func_id)] = function_decl;

diff  --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
index 8ef4f21a69694..10e8cbd11482d 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
@@ -59,11 +59,9 @@ struct FindMembersSize : public TypeVisitorCallbacks {
   TpiStream &tpi;
   llvm::Error visitKnownMember(CVMemberRecord &cvr,
                                DataMemberRecord &member) override {
-    auto it = members_info.insert(
+    members_info.insert(
         {member.getFieldOffset(),
          {llvm::codeview::RegisterId::NONE, GetSizeOfType(member.Type, tpi)}});
-    if (!it.second)
-      return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record);
     return llvm::Error::success();
   }
 };
@@ -586,7 +584,8 @@ static RegisterId GetBaseFrameRegister(PdbIndex &index,
                                        PdbCompilandSymId frame_proc_id,
                                        bool is_parameter) {
   CVSymbol frame_proc_cvs = index.ReadSymbolRecord(frame_proc_id);
-  lldbassert(frame_proc_cvs.kind() == S_FRAMEPROC);
+  if (frame_proc_cvs.kind() != S_FRAMEPROC)
+    return RegisterId::NONE;
 
   FrameProcSym frame_proc(SymbolRecordKind::FrameProcSym);
   cantFail(SymbolDeserializer::deserializeAs<FrameProcSym>(frame_proc_cvs,
@@ -658,7 +657,8 @@ VariableInfo lldb_private::npdb::GetVariableLocationInfo(
 
       RegisterId base_reg =
           GetBaseFrameRegister(index, frame_proc_id, result.is_param);
-
+      if (base_reg == RegisterId::NONE)
+        break;
       if (base_reg == RegisterId::VFRAME) {
         llvm::StringRef program;
         if (GetFrameDataProgram(index, ranges, program)) {
@@ -719,12 +719,29 @@ VariableInfo lldb_private::npdb::GetVariableLocationInfo(
       bool is_simple_type = result.type.isSimple();
       if (!is_simple_type) {
         CVType class_cvt = index.tpi().getType(result.type);
-        ClassRecord class_record = CVTagRecord::create(class_cvt).asClass();
-        CVType field_list = index.tpi().getType(class_record.FieldList);
-        FindMembersSize find_members_size(members_info, index.tpi());
-        if (llvm::Error err =
-                visitMemberRecordStream(field_list.data(), find_members_size)) {
-          llvm::consumeError(std::move(err));
+        TypeIndex class_id = result.type;
+        if (class_cvt.kind() == LF_MODIFIER)
+          class_id = LookThroughModifierRecord(class_cvt);
+        if (IsForwardRefUdt(class_id, index.tpi())) {
+          auto expected_full_ti =
+              index.tpi().findFullDeclForForwardRef(class_id);
+          if (!expected_full_ti) {
+            llvm::consumeError(expected_full_ti.takeError());
+            break;
+          }
+          class_cvt = index.tpi().getType(*expected_full_ti);
+        }
+        if (IsTagRecord(class_cvt)) {
+          TagRecord tag_record = CVTagRecord::create(class_cvt).asTag();
+          CVType field_list = index.tpi().getType(tag_record.FieldList);
+          FindMembersSize find_members_size(members_info, index.tpi());
+          if (llvm::Error err = visitMemberRecordStream(field_list.data(),
+                                                        find_members_size)) {
+            llvm::consumeError(std::move(err));
+            break;
+          }
+        } else {
+          // TODO: Handle poiner type.
           break;
         }
       }


        


More information about the lldb-commits mailing list