1 // Copyright 2020 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_TOOLS_V8WINDBG_SRC_OBJECT_INSPECTION_H_ 6 #define V8_TOOLS_V8WINDBG_SRC_OBJECT_INSPECTION_H_ 7 8 #include <comutil.h> 9 #include <wrl/implements.h> 10 11 #include <sstream> 12 #include <string> 13 #include <vector> 14 15 #include "tools/v8windbg/base/dbgext.h" 16 #include "tools/v8windbg/src/v8-debug-helper-interop.h" 17 #include "tools/v8windbg/src/v8windbg-extension.h" 18 19 // The representation of the underlying V8 object that will be cached on the 20 // DataModel representation. (Needs to implement IUnknown). 21 class __declspec(uuid("6392E072-37BB-4220-A5FF-114098923A02")) IV8CachedObject 22 : public IUnknown { 23 public: 24 virtual HRESULT __stdcall GetCachedV8HeapObject( 25 V8HeapObject** pp_heap_object) = 0; 26 }; 27 28 class V8CachedObject 29 : public WRL::RuntimeClass< 30 WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>, 31 IV8CachedObject> { 32 public: 33 V8CachedObject(Location location, std::string uncompressed_type_name, 34 WRL::ComPtr<IDebugHostContext> context, bool is_compressed); 35 V8CachedObject(V8HeapObject heap_object); 36 ~V8CachedObject() override; 37 38 static HRESULT Create(IModelObject* p_v8_object_instance, 39 IV8CachedObject** result); 40 41 IFACEMETHOD(GetCachedV8HeapObject)(V8HeapObject** pp_heap_object); 42 43 private: 44 // The properties and description of the object, if already read. 45 V8HeapObject heap_object_; 46 bool heap_object_initialized_ = false; 47 48 // Data that is necessary for reading the object. 49 Location location_; 50 std::string uncompressed_type_name_; 51 WRL::ComPtr<IDebugHostContext> context_; 52 bool is_compressed_ = false; 53 }; 54 55 // A simple COM wrapper class to hold data required for IndexedFieldParent. 56 // (Needs to implement IUnknown). 57 class __declspec(uuid("6392E072-37BB-4220-A5FF-114098923A03")) IIndexedFieldData 58 : public IUnknown { 59 public: 60 // Get a pointer to the Property object held by this IIndexedFieldData. The 61 // pointer returned in this way is valid only while the containing 62 // IIndexedFieldData is alive. 63 virtual HRESULT __stdcall GetProperty(Property** property) = 0; 64 }; 65 66 class IndexedFieldData 67 : public WRL::RuntimeClass< 68 WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>, 69 IIndexedFieldData> { 70 public: 71 IndexedFieldData(Property property); 72 ~IndexedFieldData() override; 73 74 // Get a pointer to the Property object held by this IndexedFieldData. The 75 // pointer returned in this way is valid only while the containing 76 // IndexedFieldData is alive. 77 IFACEMETHOD(GetProperty)(Property** property); 78 79 private: 80 Property property_; 81 }; 82 83 // A parent model that provides indexing support for fields that contain arrays 84 // of something more complicated than basic native types. 85 class IndexedFieldParent 86 : public WRL::RuntimeClass< 87 WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>, 88 IDataModelConcept, IIterableConcept, IIndexableConcept> { 89 public: 90 // IDataModelConcept 91 IFACEMETHOD(InitializeObject) 92 (IModelObject* model_object, IDebugHostTypeSignature* matching_type_signature, 93 IDebugHostSymbolEnumerator* wildcard_matches); 94 95 // IDataModelConcept 96 IFACEMETHOD(GetName)(BSTR* model_name); 97 98 // IIndexableConcept 99 IFACEMETHOD(GetAt) 100 (IModelObject* context_object, ULONG64 indexer_count, IModelObject** indexers, 101 _COM_Errorptr_ IModelObject** object, IKeyStore** metadata); 102 103 // IIndexableConcept 104 IFACEMETHOD(GetDimensionality) 105 (IModelObject* context_object, ULONG64* dimensionality); 106 107 // IIndexableConcept 108 IFACEMETHOD(SetAt) 109 (IModelObject* context_object, ULONG64 indexer_count, IModelObject** indexers, 110 IModelObject* value); 111 112 // IIterableConcept 113 IFACEMETHOD(GetDefaultIndexDimensionality) 114 (IModelObject* context_object, ULONG64* dimensionality); 115 116 // IIterableConcept 117 IFACEMETHOD(GetIterator) 118 (IModelObject* context_object, IModelIterator** iterator); 119 }; 120 121 // An iterator for the values within an array field. 122 class IndexedFieldIterator 123 : public WRL::RuntimeClass< 124 WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>, 125 IModelIterator> { 126 public: 127 IndexedFieldIterator(IModelObject* context_object); 128 ~IndexedFieldIterator() override; 129 130 IFACEMETHOD(Reset)(); 131 132 IFACEMETHOD(GetNext) 133 (IModelObject** object, ULONG64 dimensions, IModelObject** indexers, 134 IKeyStore** metadata); 135 136 private: 137 size_t next_ = 0; 138 WRL::ComPtr<IModelObject> context_object_; 139 }; 140 141 // Enumerates the names of fields on V8 objects. 142 class V8ObjectKeyEnumerator 143 : public WRL::RuntimeClass< 144 WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>, 145 IKeyEnumerator> { 146 public: 147 V8ObjectKeyEnumerator(WRL::ComPtr<IV8CachedObject>& v8_cached_object); 148 ~V8ObjectKeyEnumerator() override; 149 150 IFACEMETHOD(Reset)(); 151 152 // This method will be called with a nullptr 'value' for each key if returned 153 // from an IDynamicKeyProviderConcept. It will call GetKey on the 154 // IDynamicKeyProviderConcept interface after each key returned. 155 IFACEMETHOD(GetNext)(BSTR* key, IModelObject** value, IKeyStore** metadata); 156 157 private: 158 int index_ = 0; 159 WRL::ComPtr<IV8CachedObject> sp_v8_cached_object_; 160 }; 161 162 // A parent model for V8 handle types such as v8::internal::Handle<*>. 163 class V8LocalDataModel 164 : public WRL::RuntimeClass< 165 WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>, 166 IDataModelConcept> { 167 public: 168 IFACEMETHOD(InitializeObject) 169 (IModelObject* model_object, IDebugHostTypeSignature* matching_type_signature, 170 IDebugHostSymbolEnumerator* wildcard_matches); 171 172 IFACEMETHOD(GetName)(BSTR* model_name); 173 }; 174 175 // A parent model for V8 object types such as v8::internal::Object. 176 class V8ObjectDataModel 177 : public WRL::RuntimeClass< 178 WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>, 179 IDataModelConcept, IStringDisplayableConcept, 180 IDynamicKeyProviderConcept> { 181 public: GetCachedObject(IModelObject * context_object,IV8CachedObject ** result)182 HRESULT GetCachedObject(IModelObject* context_object, 183 IV8CachedObject** result) { 184 // Get the IModelObject for this parent object. As it is a dynamic provider, 185 // there is only one parent directly on the object. 186 WRL::ComPtr<IModelObject> sp_parent_model, sp_context_adjuster; 187 RETURN_IF_FAIL(context_object->GetParentModel(0, &sp_parent_model, 188 &sp_context_adjuster)); 189 190 // See if the cached object is already present 191 WRL::ComPtr<IUnknown> sp_context; 192 HRESULT hr = context_object->GetContextForDataModel(sp_parent_model.Get(), 193 &sp_context); 194 195 WRL::ComPtr<IV8CachedObject> sp_v8_cached_object; 196 197 if (SUCCEEDED(hr)) { 198 RETURN_IF_FAIL(sp_context.As(&sp_v8_cached_object)); 199 } else { 200 RETURN_IF_FAIL( 201 V8CachedObject::Create(context_object, &sp_v8_cached_object)); 202 RETURN_IF_FAIL(sp_v8_cached_object.As(&sp_context)); 203 RETURN_IF_FAIL(context_object->SetContextForDataModel( 204 sp_parent_model.Get(), sp_context.Get())); 205 } 206 207 *result = sp_v8_cached_object.Detach(); 208 return S_OK; 209 } 210 211 IFACEMETHOD(InitializeObject) 212 (IModelObject* model_object, IDebugHostTypeSignature* matching_type_signature, 213 IDebugHostSymbolEnumerator* wildcard_matches); 214 215 IFACEMETHOD(GetName)(BSTR* model_name); 216 217 IFACEMETHOD(ToDisplayString) 218 (IModelObject* context_object, IKeyStore* metadata, BSTR* display_string); 219 220 // IDynamicKeyProviderConcept 221 IFACEMETHOD(GetKey) 222 (IModelObject* context_object, PCWSTR key, IModelObject** key_value, 223 IKeyStore** metadata, bool* has_key); 224 225 IFACEMETHOD(SetKey) 226 (IModelObject* context_object, PCWSTR key, IModelObject* key_value, 227 IKeyStore* metadata); 228 229 IFACEMETHOD(EnumerateKeys) 230 (IModelObject* context_object, IKeyEnumerator** pp_enumerator); 231 }; 232 233 // The implemention of the "Value" getter for V8 handle types. 234 class V8LocalValueProperty 235 : public WRL::RuntimeClass< 236 WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>, 237 IModelPropertyAccessor> { 238 public: 239 IFACEMETHOD(GetValue) 240 (PCWSTR pwsz_key, IModelObject* p_v8_object_instance, 241 IModelObject** pp_value); 242 243 IFACEMETHOD(SetValue) 244 (PCWSTR /*pwsz_key*/, IModelObject* /*p_process_instance*/, 245 IModelObject* /*p_value*/); 246 }; 247 248 // The implemention of the "NodeId" getter for v8::internal::compiler::Node 249 // type. 250 class V8InternalCompilerNodeIdProperty 251 : public WRL::RuntimeClass< 252 WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>, 253 IModelPropertyAccessor> { 254 public: 255 IFACEMETHOD(GetValue) 256 (PCWSTR pwsz_key, IModelObject* p_v8_object_instance, 257 IModelObject** pp_value); 258 259 IFACEMETHOD(SetValue) 260 (PCWSTR /*pwsz_key*/, IModelObject* /*p_process_instance*/, 261 IModelObject* /*p_value*/); 262 }; 263 264 // The implemention of the "bitset_name" getter for v8::internal::compiler::Type 265 // type. 266 class V8InternalCompilerBitsetNameProperty 267 : public WRL::RuntimeClass< 268 WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>, 269 IModelPropertyAccessor> { 270 public: 271 IFACEMETHOD(GetValue) 272 (PCWSTR pwsz_key, IModelObject* p_v8_compiler_type_instance, 273 IModelObject** pp_value); 274 275 IFACEMETHOD(SetValue) 276 (PCWSTR /*pwsz_key*/, IModelObject* /*p_process_instance*/, 277 IModelObject* /*p_value*/); 278 }; 279 280 // A way that someone can directly inspect a tagged value, even if that value 281 // isn't in memory (from a register, or the user's imagination, etc.). 282 class InspectV8ObjectMethod 283 : public WRL::RuntimeClass< 284 WRL::RuntimeClassFlags<WRL::RuntimeClassType::ClassicCom>, 285 IModelMethod> { 286 public: 287 IFACEMETHOD(Call) 288 (IModelObject* p_context_object, ULONG64 arg_count, 289 _In_reads_(arg_count) IModelObject** pp_arguments, IModelObject** pp_result, 290 IKeyStore** pp_metadata); 291 }; 292 293 HRESULT GetModelForProperty(const Property& prop, 294 WRL::ComPtr<IDebugHostContext>& sp_ctx, 295 IModelObject** result); 296 297 #endif // V8_TOOLS_V8WINDBG_SRC_OBJECT_INSPECTION_H_ 298