[Lldb-commits] [PATCH] D51967: [PDB] Use the raw PDB symbol interface more accurately

Aleksandr Urakov via Phabricator via lldb-commits lldb-commits at lists.llvm.org
Thu Sep 13 04:21:37 PDT 2018

aleksandr.urakov added a comment.

In https://reviews.llvm.org/D51967#1232534, @zturner wrote:

> I've been experimenting with DIA locally and after some investigation I'm not sure this is going to be reliable.  Let's say we have a class, we want the decl context containing the class.  For example, on line 366.  So we call `GetDeclContextContainingSymbol`.  Despite what the MSDN documentation states, I'm pretty sure this is going to return a `PDBSymbolExe`.

But it returns the parent UDT symbol for me, when it is called for inner classes... I've added the next assert before return at the line 288:

  assert(tag != PDB_SymType::UDT);

and have run the AST test:

  llvm-lit.py -v ..\..\tools\lldb\lit\SymbolFile\PDB\ast-restore.test

and have retrieved the crash dump:

  Assertion failed: tag != PDB_SymType::UDT, file ..\tools\lldb\source\Plugins\SymbolFile\PDB\PDBASTParser.cpp, line 288
  LLVMSymbolizer: error reading file: 'ucrtbased.pdb': no such file or directory
  LLVMSymbolizer: error reading file: 'wkernel32.pdb': no such file or directory
  LLVMSymbolizer: error reading file: 'wntdll.pdb': no such file or directory
  #0 0x0107f359 HandleAbort c:\work\llvm\lib\support\windows\signals.inc:409:0
  #1 0x77dbf82b (C:\WINDOWS\SYSTEM32\ucrtbased.dll+0x9f82b)
  #2 0x77dc0d72 (C:\WINDOWS\SYSTEM32\ucrtbased.dll+0xa0d72)
  #3 0x77dc5124 (C:\WINDOWS\SYSTEM32\ucrtbased.dll+0xa5124)
  #4 0x77dc371a (C:\WINDOWS\SYSTEM32\ucrtbased.dll+0xa371a)
  #5 0x77dc568a (C:\WINDOWS\SYSTEM32\ucrtbased.dll+0xa568a)
  #6 0x01e1c575 GetClassOrFunctionParent c:\work\llvm\tools\lldb\source\plugins\symbolfile\pdb\pdbastparser.cpp:288:0
  #7 0x01e19c19 PDBASTParser::GetDeclContextContainingSymbol(class llvm::pdb::PDBSymbol const &) c:\work\llvm\tools\lldb\source\plugins\symbolfile\pdb\pdbastparser.cpp:907:0
  #8 0x01e16ee4 PDBASTParser::CreateLLDBTypeFromPDBType(class llvm::pdb::PDBSymbol const &) c:\work\llvm\tools\lldb\source\plugins\symbolfile\pdb\pdbastparser.cpp:373:0
  #9 0x01df71ae SymbolFilePDB::ResolveTypeUID(unsigned __int64) c:\work\llvm\tools\lldb\source\plugins\symbolfile\pdb\symbolfilepdb.cpp:563:0
  #10 0x01e1aa2d PDBASTParser::CompleteTypeFromUDT(class lldb_private::SymbolFile &,class lldb_private::CompilerType &,class llvm::pdb::PDBSymbolTypeUDT &) c:\work\llvm\tools\lldb\source\plugins\symbolfile\pdb\pdbastparser.cpp:1088:0
  #11 0x01e19345 PDBASTParser::CompleteTypeFromPDB(class lldb_private::CompilerType &) c:\work\llvm\tools\lldb\source\plugins\symbolfile\pdb\pdbastparser.cpp:768:0
  #12 0x01df73ab SymbolFilePDB::CompleteType(class lldb_private::CompilerType &) c:\work\llvm\tools\lldb\source\plugins\symbolfile\pdb\symbolfilepdb.cpp:585:0
  #13 0x014fa4ea lldb_private::Type::ResolveClangType(enum lldb_private::Type::ResolveStateTag) c:\work\llvm\tools\lldb\source\symbol\type.cpp:552:0
  #14 0x014f9a08 lldb_private::Type::GetFullCompilerType(void) c:\work\llvm\tools\lldb\source\symbol\type.cpp:593:0
  #15 0x01e19566 PDBASTParser::GetDeclForSymbol(class llvm::pdb::PDBSymbol const &) c:\work\llvm\tools\lldb\source\plugins\symbolfile\pdb\pdbastparser.cpp:798:0
  #16 0x01e1a2c3 PDBASTParser::ParseDeclsForDeclContext(class clang::DeclContext const *) c:\work\llvm\tools\lldb\source\plugins\symbolfile\pdb\pdbastparser.cpp:992:0
  #17 0x01df78d2 SymbolFilePDB::ParseDeclsForContext(class lldb_private::CompilerDeclContext) c:\work\llvm\tools\lldb\source\plugins\symbolfile\pdb\symbolfilepdb.cpp:665:0
  #18 0x00fde8d3 opts::symbols::dumpAST c:\work\llvm\tools\lldb\tools\lldb-test\lldb-test.cpp:537:0
  #19 0x00fdf6a5 opts::symbols::dumpSymbols c:\work\llvm\tools\lldb\tools\lldb-test\lldb-test.cpp:710:0
  #20 0x00fe0f9d main c:\work\llvm\tools\lldb\tools\lldb-test\lldb-test.cpp:952:0
  #21 0x078e219e invoke_main f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:78:0
  #22 0x078e2037 _scrt_common_main_seh f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:288:0
  #23 0x078e1ecd _scrt_common_main f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:331:0
  #24 0x078e2218 mainCRTStartup f:\dd\vctools\crt\vcstartup\src\startup\exe_main.cpp:17:0
  #25 0x76558484 (C:\WINDOWS\System32\KERNEL32.DLL+0x18484)
  #26 0x770a2fea (C:\WINDOWS\SYSTEM32\ntdll.dll+0x62fea)
  #27 0x770a2fba (C:\WINDOWS\SYSTEM32\ntdll.dll+0x62fba)

During debugging I have figured out that it was `N0::N1::Class::Inner` resolving, and it had retrieved `N0::N1::Class` as a class parent here (which was completing at the time, and that completion had invoked `N0::N1::Class::Inner` resolving). So it seems that it works in this case.

> Worse, there is no guarantee that `getLexicalParent()` or `getClassParent()` will return the same thing twice.  It all depends on how you obtained the object in the first place.

Yes, I understand, that sometimes this function does not return a valid parent and returns nullptr. That's why I additionally check the symbol name at lines 913-943. It may fire, for example, for class static variables, for which DIA returns two symbols: one has a class parent (and has a short name e.g. `ClassStatic`) when another has not and treated as a global (and has a full name e.g. `N0::N1::Class::ClassStatic`).

For myself, I prove the correctness of `GetClassOrFunctionParent` from its postconditions. It may return only:

- nullptr;
- lexical parent symbol, which is a function (line 306). We check it in the line 305;
- class parent symbol, which is a class (line 288). It must be a class, because all symbol types allowed in the outer switch must return a class symbol or nullptr as a class parent (if I'm not mistaken). But we filter nullptr in the line 287, so in the line 288 only a class symbol may be returned.

So it returns nullptr or a valid enclosing function or class. In the first case the symbol still can belong to a class or a function (as a class static variables described above), then we try to find a parent with the name. Unfortunately, there is a kind of heuristics here, but I have no idea yet how to do it better...


More information about the lldb-commits mailing list