zturner updated this revision to Diff 177243.
zturner added a comment.
Add some comments regarding fixing `DeclContext` reconstruction.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D55384/new/
https://reviews.llvm.org/D55384
Files:
lldb/lit/SymbolFile/NativePDB/Inputs/ast-functions.lldbinit
lldb/lit/SymbolFile/NativePDB/Inputs/ast-reconstruction.lldbinit
lldb/lit/SymbolFile/NativePDB/Inputs/ast-types.lldbinit
lldb/lit/SymbolFile/NativePDB/ast-functions-msvc.cpp
lldb/lit/SymbolFile/NativePDB/ast-functions.cpp
lldb/lit/SymbolFile/NativePDB/ast-reconstruction.cpp
lldb/lit/SymbolFile/NativePDB/ast-types.cpp
lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
llvm/include/llvm/DebugInfo/CodeView/SymbolRecordHelpers.h
llvm/include/llvm/Support/BinaryStreamArray.h
llvm/lib/DebugInfo/CodeView/SymbolRecordHelpers.cpp
Index: llvm/lib/DebugInfo/CodeView/SymbolRecordHelpers.cpp
===================================================================
--- llvm/lib/DebugInfo/CodeView/SymbolRecordHelpers.cpp
+++ llvm/lib/DebugInfo/CodeView/SymbolRecordHelpers.cpp
@@ -50,4 +50,15 @@
assert(false && "Unknown record type");
return 0;
}
-}
\ No newline at end of file
+}
+
+CVSymbolArray
+llvm::codeview::limitSymbolArrayToScope(const CVSymbolArray &Symbols,
+ uint32_t ScopeBegin) {
+ CVSymbol Opener = *Symbols.at(ScopeBegin);
+ assert(symbolOpensScope(Opener.kind()));
+ uint32_t EndOffset = getScopeEndOffset(Opener);
+ CVSymbol Closer = *Symbols.at(EndOffset);
+ EndOffset += Closer.RecordData.size();
+ return Symbols.substream(ScopeBegin, EndOffset);
+}
Index: llvm/include/llvm/Support/BinaryStreamArray.h
===================================================================
--- llvm/include/llvm/Support/BinaryStreamArray.h
+++ llvm/include/llvm/Support/BinaryStreamArray.h
@@ -113,6 +113,15 @@
bool empty() const { return Stream.getLength() == 0; }
+ VarStreamArray<ValueType, Extractor> substream(uint32_t Begin,
+ uint32_t End) const {
+ assert(Begin >= Skew);
+ // We should never cut off the beginning of the stream since it might be
+ // skewed, meaning the initial bytes are important.
+ BinaryStreamRef NewStream = Stream.slice(0, End);
+ return {NewStream, E, Begin};
+ }
+
/// given an offset into the array's underlying stream, return an
/// iterator to the record at that offset. This is considered unsafe
/// since the behavior is undefined if \p Offset does not refer to the
Index: llvm/include/llvm/DebugInfo/CodeView/SymbolRecordHelpers.h
===================================================================
--- llvm/include/llvm/DebugInfo/CodeView/SymbolRecordHelpers.h
+++ llvm/include/llvm/DebugInfo/CodeView/SymbolRecordHelpers.h
@@ -50,7 +50,11 @@
/// Given a symbol P for which symbolOpensScope(P) == true, return the
/// corresponding end offset.
-uint32_t getScopeEndOffset(const CVSymbol &symbol);
+uint32_t getScopeEndOffset(const CVSymbol &Symbol);
+
+CVSymbolArray limitSymbolArrayToScope(const CVSymbolArray &Symbols,
+ uint32_t ScopeBegin);
+
} // namespace codeview
} // namespace llvm
Index: lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
+++ lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
@@ -112,6 +112,8 @@
size_t ParseVariablesForContext(const SymbolContext &sc) override {
return 0;
}
+
+ CompilerDeclContext GetDeclContextContainingUID(lldb::user_id_t uid) override;
Type *ResolveTypeUID(lldb::user_id_t type_uid) override;
llvm::Optional<ArrayInfo> GetDynamicArrayInfoForUID(
lldb::user_id_t type_uid,
@@ -217,7 +219,7 @@
llvm::DenseMap<clang::TagDecl *, DeclStatus> m_decl_to_status;
- llvm::DenseMap<lldb::user_id_t, clang::TagDecl *> m_uid_to_decl;
+ llvm::DenseMap<lldb::user_id_t, clang::Decl *> m_uid_to_decl;
llvm::DenseMap<llvm::codeview::TypeIndex, llvm::codeview::TypeIndex>
m_parent_types;
Index: lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -37,6 +37,7 @@
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
#include "llvm/DebugInfo/CodeView/RecordName.h"
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
@@ -538,16 +539,114 @@
if (!func_range.GetBaseAddress().IsValid())
return nullptr;
- Type *func_type = nullptr;
+ ProcSym proc(static_cast<SymbolRecordKind>(sym_record.kind()));
+ cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym_record, proc));
+ TypeSP func_type = GetOrCreateType(proc.FunctionType);
- // FIXME: Resolve types and mangled names.
- PdbTypeSymId sig_id(TypeIndex::None(), false);
- Mangled mangled(getSymbolName(sym_record));
+ PdbTypeSymId sig_id(proc.FunctionType, false);
+ Mangled mangled(proc.Name);
FunctionSP func_sp = std::make_shared<Function>(
sc.comp_unit, toOpaqueUid(func_id), toOpaqueUid(sig_id), mangled,
- func_type, func_range);
+ func_type.get(), func_range);
sc.comp_unit->AddFunction(func_sp);
+
+ clang::StorageClass storage = clang::SC_None;
+ if (sym_record.kind() == S_LPROC32)
+ storage = clang::SC_Static;
+
+ // There are two ways we could retrieve the parameter list. The first is by
+ // iterating the arguments on the function signature type, however that would
+ // only tell us the types of the arguments and not the names. The second is
+ // to iterate the CVSymbol records that follow the S_GPROC32 / S_LPROC32 until
+ // we have the correct number of arguments as stated by the function
+ // signature. The latter has more potential to go wrong in the face of
+ // improper debug info simply because we're assuming more about the layout of
+ // the records, but it is the only way to get argument names.
+ CVType sig_cvt;
+ CVType arg_list_cvt;
+ ProcedureRecord sig_record;
+ ArgListRecord arg_list_record;
+
+ sig_cvt = m_index->tpi().getType(proc.FunctionType);
+ if (sig_cvt.kind() != LF_PROCEDURE)
+ return func_sp;
+ cantFail(
+ TypeDeserializer::deserializeAs<ProcedureRecord>(sig_cvt, sig_record));
+
+ CompilerDeclContext context =
+ GetDeclContextContainingUID(toOpaqueUid(func_id));
+
+ clang::DeclContext *decl_context =
+ static_cast<clang::DeclContext *>(context.GetOpaqueDeclContext());
+ clang::FunctionDecl *function_decl = m_clang->CreateFunctionDeclaration(
+ decl_context, proc.Name.str().c_str(),
+ func_type->GetForwardCompilerType(), storage, false);
+
+ lldbassert(m_uid_to_decl.count(toOpaqueUid(func_id)) == 0);
+ m_uid_to_decl[toOpaqueUid(func_id)] = function_decl;
+ CVSymbolArray scope = limitSymbolArrayToScope(
+ cci->m_debug_stream.getSymbolArray(), func_id.offset);
+
+ uint32_t params_remaining = sig_record.getParameterCount();
+ auto begin = scope.begin();
+ auto end = scope.end();
+ std::vector<clang::ParmVarDecl *> params;
+ while (begin != end && params_remaining > 0) {
+ uint32_t record_offset = begin.offset();
+ CVSymbol sym = *begin++;
+
+ TypeIndex param_type;
+ llvm::StringRef param_name;
+ switch (sym.kind()) {
+ case S_REGREL32: {
+ RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
+ cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
+ param_type = reg.Type;
+ param_name = reg.Name;
+ break;
+ }
+ case S_REGISTER: {
+ RegisterSym reg(SymbolRecordKind::RegisterSym);
+ cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
+ param_type = reg.Index;
+ param_name = reg.Name;
+ break;
+ }
+ case S_LOCAL: {
+ LocalSym local(SymbolRecordKind::LocalSym);
+ cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
+ if ((local.Flags & LocalSymFlags::IsParameter) == LocalSymFlags::None)
+ continue;
+ param_type = local.Type;
+ param_name = local.Name;
+ break;
+ }
+ case S_BLOCK32:
+ // All parameters should come before the first block. If that isn't the
+ // case, then perhaps this is bad debug info that doesn't contain
+ // information about all parameters.
+ params_remaining = 0;
+ continue;
+ default:
+ continue;
+ }
+
+ PdbCompilandSymId param_uid(func_id.modi, record_offset);
+ TypeSP type_sp = GetOrCreateType(param_type);
+ clang::ParmVarDecl *param = m_clang->CreateParameterDeclaration(
+ param_name.str().c_str(), type_sp->GetForwardCompilerType(),
+ clang::SC_None);
+ lldbassert(m_uid_to_decl.count(toOpaqueUid(param_uid)) == 0);
+
+ m_uid_to_decl[toOpaqueUid(param_uid)] = param;
+ params.push_back(param);
+ --params_remaining;
+ }
+
+ if (!params.empty())
+ m_clang->SetFunctionParameters(function_decl, params.data(), params.size());
+
return func_sp;
}
@@ -711,9 +810,16 @@
return false;
}
+static clang::DeclContext *
+GetDeclContextForNamespaceScope(ClangASTContext &clang, llvm::StringRef scope) {
+ return clang.GetTranslationUnitDecl();
+}
+
std::pair<clang::DeclContext *, std::string>
SymbolFileNativePDB::CreateDeclInfoForType(const TagRecord &record,
TypeIndex ti) {
+ // FIXME: Move this to GetDeclContextContainingUID.
+
llvm::ms_demangle::Demangler demangler;
StringView sv(record.UniqueName.begin(), record.UniqueName.size());
llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv);
@@ -1520,6 +1626,32 @@
size_t SymbolFileNativePDB::ParseTypes(const SymbolContext &sc) { return 0; }
+CompilerDeclContext
+SymbolFileNativePDB::GetDeclContextContainingUID(lldb::user_id_t uid) {
+ // FIXME: This should look up the uid, decide if it's a symbol or a type, and
+ // depending which it is, find the appropriate DeclContext. Possibilities:
+ // For classes and typedefs:
+ // * Function
+ // * Namespace
+ // * Global
+ // * Block
+ // * Class
+ // For field list members:
+ // * Class
+ // For variables:
+ // * Function
+ // * Namespace
+ // * Global
+ // * Block
+ // For functions:
+ // * Namespace
+ // * Global
+ // * Class
+ //
+ // It is an error to call this function with a uid for any other symbol type.
+ return {m_clang, m_clang->GetTranslationUnitDecl()};
+}
+
Type *SymbolFileNativePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
auto iter = m_types.find(type_uid);
// lldb should not be passing us non-sensical type uids. the only way it
Index: lldb/lit/SymbolFile/NativePDB/ast-types.cpp
===================================================================
--- lldb/lit/SymbolFile/NativePDB/ast-types.cpp
+++ lldb/lit/SymbolFile/NativePDB/ast-types.cpp
@@ -4,7 +4,7 @@
// Test various interesting cases for AST reconstruction.
// RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s
// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
-// RUN: %p/Inputs/ast-reconstruction.lldbinit 2>&1 | FileCheck %s
+// RUN: %p/Inputs/ast-types.lldbinit 2>&1 | FileCheck %s
// Test trivial versions of each tag type.
class TrivialC {};
Index: lldb/lit/SymbolFile/NativePDB/ast-functions.cpp
===================================================================
--- /dev/null
+++ lldb/lit/SymbolFile/NativePDB/ast-functions.cpp
@@ -0,0 +1,29 @@
+// clang-format off
+// REQUIRES: lld
+
+// RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s
+
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
+// RUN: %p/Inputs/ast-functions.lldbinit 2>&1 | FileCheck %s
+
+static int static_fn() {
+ return 42;
+}
+
+int varargs_fn(int x, int y, ...) {
+ return x + y;
+}
+
+int main(int argc, char **argv) {
+ return static_fn() + varargs_fn(argc, argc);
+}
+
+// CHECK: TranslationUnitDecl
+// CHECK-NEXT: |-FunctionDecl {{.*}} main 'int (int, char **)'
+// CHECK-NEXT: | |-ParmVarDecl {{.*}} argc 'int'
+// CHECK-NEXT: | `-ParmVarDecl {{.*}} argv 'char **'
+// CHECK-NEXT: |-FunctionDecl {{.*}} static_fn 'int ()' static
+// CHECK-NEXT: |-FunctionDecl {{.*}} varargs_fn 'int (int, int, ...)'
+// CHECK-NEXT: | |-ParmVarDecl {{.*}} x 'int'
+// CHECK-NEXT: | `-ParmVarDecl {{.*}} y 'int'
+// CHECK-NEXT: `-<undeserialized declarations>
Index: lldb/lit/SymbolFile/NativePDB/ast-functions-msvc.cpp
===================================================================
--- /dev/null
+++ lldb/lit/SymbolFile/NativePDB/ast-functions-msvc.cpp
@@ -0,0 +1,7 @@
+// clang-format off
+// REQUIRES: msvc
+
+// RUN: %build --compiler=msvc --nodefaultlib -o %t.exe -- %S/ast-functions.cpp
+
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
+// RUN: %p/Inputs/ast-functions.lldbinit 2>&1 | FileCheck %S/ast-functions.cpp
Index: lldb/lit/SymbolFile/NativePDB/Inputs/ast-functions.lldbinit
===================================================================
--- /dev/null
+++ lldb/lit/SymbolFile/NativePDB/Inputs/ast-functions.lldbinit
@@ -0,0 +1,8 @@
+
+break set -n main
+break set -n static_fn
+break set -n varargs_fn
+
+target modules dump ast
+
+quit
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits