Skip to content

Commit 2e3d3a9

Browse files
authored
Visualizer should try to find winmd for interface and property types, and should fail more gracefully when not found. (#864)
1 parent 39c062e commit 2e3d3a9

File tree

4 files changed

+44
-9
lines changed

4 files changed

+44
-9
lines changed

natvis/cppwinrt_visualizer.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,14 @@ void LoadMetadata(DkmProcess* process, WCHAR const* processPath, std::string_vie
100100
if (FindMetadata(process, winmd_path))
101101
{
102102
MetadataDiagnostic(process, L"Loaded ", winmd_path);
103-
db_files.push_back(winmd_path.string());
104-
db->add_database(winmd_path.string());
103+
104+
auto const path_string = winmd_path.string();
105+
106+
if (std::find(db_files.begin(), db_files.end(), path_string) == db_files.end())
107+
{
108+
db->add_database(path_string);
109+
db_files.push_back(path_string);
110+
}
105111
}
106112
auto pos = probe_file.rfind('.');
107113
if (pos == std::string::npos)
@@ -129,6 +135,19 @@ TypeDef FindType(DkmProcess* process, std::string_view const& typeName)
129135
return type;
130136
}
131137

138+
TypeDef FindType(DkmProcess* process, std::string_view const& typeNamespace, std::string_view const& typeName)
139+
{
140+
auto type = db->find(typeNamespace, typeName);
141+
if (!type)
142+
{
143+
std::string fullName(typeNamespace);
144+
fullName.append(".");
145+
fullName.append(typeName);
146+
FindType(process, fullName);
147+
}
148+
return type;
149+
}
150+
132151
cppwinrt_visualizer::cppwinrt_visualizer()
133152
{
134153
try

natvis/object_visualizer.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,11 @@ void GetInterfaceData(
361361
_Inout_ std::vector<PropertyData>& propertyData,
362362
_Out_ bool& isStringable
363363
){
364-
auto [type, propIid] = ResolveTypeInterface(index);
364+
auto [type, propIid] = ResolveTypeInterface(process, index);
365+
if (!type)
366+
{
367+
return;
368+
}
365369

366370
if (propIid == IID_IStringable)
367371
{
@@ -402,7 +406,12 @@ void GetInterfaceData(
402406
},
403407
[&](coded_index<TypeDefOrRef> const& index)
404408
{
405-
auto type = ResolveType(index);
409+
auto type = ResolveType(process, index);
410+
if (!type)
411+
{
412+
return;
413+
}
414+
406415
auto typeName = type.TypeName();
407416
if (typeName == "GUID"sv)
408417
{

natvis/pch.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,21 +89,22 @@ inline bool starts_with(std::string_view const& value, std::string_view const& m
8989
}
9090

9191
winmd::reader::TypeDef FindType(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& typeName);
92+
winmd::reader::TypeDef FindType(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& typeNamespace, std::string_view const& typeName);
9293

93-
inline winmd::reader::TypeDef ResolveType(winmd::reader::coded_index<winmd::reader::TypeDefOrRef> index) noexcept
94+
inline winmd::reader::TypeDef ResolveType(Microsoft::VisualStudio::Debugger::DkmProcess* process, winmd::reader::coded_index<winmd::reader::TypeDefOrRef> index) noexcept
9495
{
9596
switch (index.type())
9697
{
9798
case winmd::reader::TypeDefOrRef::TypeDef:
9899
return index.TypeDef();
99100
case winmd::reader::TypeDefOrRef::TypeRef:
100-
return winmd::reader::find_required(index.TypeRef());
101+
return FindType(process, index.TypeRef().TypeNamespace(), index.TypeRef().TypeName());
101102
default: //case TypeDefOrRef::TypeSpec:
102103
return winmd::reader::find_required(index.TypeSpec().Signature().
103104
GenericTypeInst().GenericType().TypeRef());
104105
}
105106
}
106107

107-
std::pair<winmd::reader::TypeDef, std::wstring> ResolveTypeInterface(winmd::reader::coded_index<winmd::reader::TypeDefOrRef> index);
108+
std::pair<winmd::reader::TypeDef, std::wstring> ResolveTypeInterface(Microsoft::VisualStudio::Debugger::DkmProcess* process, winmd::reader::coded_index<winmd::reader::TypeDefOrRef> index);
108109

109110
void ClearTypeResolver();

natvis/type_resolver.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using namespace winrt;
44
using namespace winmd::reader;
55
using namespace std::literals;
6+
using namespace Microsoft::VisualStudio::Debugger;
67

78
static std::map<coded_index<TypeDefOrRef>, std::pair<TypeDef, std::wstring>> _cache;
89

@@ -277,14 +278,19 @@ static guid generate_guid(coded_index<TypeDefOrRef> const& type)
277278
return set_named_guid_fields(endian_swap(to_guid(calculate_sha1(buffer))));
278279
}
279280

280-
std::pair<TypeDef, std::wstring> ResolveTypeInterface(coded_index<TypeDefOrRef> index)
281+
std::pair<TypeDef, std::wstring> ResolveTypeInterface(DkmProcess* process, coded_index<TypeDefOrRef> index)
281282
{
282283
if (auto found = _cache.find(index); found != _cache.end())
283284
{
284285
return found->second;
285286
}
286287

287-
TypeDef type = ResolveType(index);
288+
TypeDef type = ResolveType(process, index);
289+
if (!type)
290+
{
291+
return {};
292+
}
293+
288294
auto guid = index.type() == TypeDefOrRef::TypeSpec ?
289295
format_guid(generate_guid(index)) : format_guid(get_guid(type));
290296

0 commit comments

Comments
 (0)