11cb0ef41Sopenharmony_ci// Copyright 2020 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "tools/v8windbg/src/local-variables.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include <vector> 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ci#include "tools/v8windbg/base/utilities.h" 101cb0ef41Sopenharmony_ci#include "tools/v8windbg/src/object-inspection.h" 111cb0ef41Sopenharmony_ci#include "tools/v8windbg/src/v8-debug-helper-interop.h" 121cb0ef41Sopenharmony_ci#include "tools/v8windbg/src/v8windbg-extension.h" 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_ciV8LocalVariables::V8LocalVariables(WRL::ComPtr<IModelPropertyAccessor> original, 151cb0ef41Sopenharmony_ci bool is_parameters) 161cb0ef41Sopenharmony_ci : original_(original), is_parameters_(is_parameters) {} 171cb0ef41Sopenharmony_ciV8LocalVariables::~V8LocalVariables() = default; 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ciIFACEMETHODIMP V8LocalVariables::GetValue(PCWSTR key, IModelObject* context, 201cb0ef41Sopenharmony_ci IModelObject** value) noexcept { 211cb0ef41Sopenharmony_ci // See if the frame can fetch locals based on symbols. If so, it's a normal 221cb0ef41Sopenharmony_ci // C++ frame, so we can be done. 231cb0ef41Sopenharmony_ci HRESULT original_hr = original_->GetValue(key, context, value); 241cb0ef41Sopenharmony_ci if (SUCCEEDED(original_hr)) return original_hr; 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_ci // Next, try to find out about the instruction pointer. If it is within the V8 271cb0ef41Sopenharmony_ci // module, or points to unknown space outside a module (generated code), then 281cb0ef41Sopenharmony_ci // we're interested. Otherwise, we have nothing useful to do. 291cb0ef41Sopenharmony_ci WRL::ComPtr<IModelObject> attributes; 301cb0ef41Sopenharmony_ci RETURN_IF_FAIL(context->GetKeyValue(L"Attributes", &attributes, nullptr)); 311cb0ef41Sopenharmony_ci WRL::ComPtr<IModelObject> boxed_instruction_offset; 321cb0ef41Sopenharmony_ci RETURN_IF_FAIL(attributes->GetKeyValue(L"InstructionOffset", 331cb0ef41Sopenharmony_ci &boxed_instruction_offset, nullptr)); 341cb0ef41Sopenharmony_ci ULONG64 instruction_offset{}; 351cb0ef41Sopenharmony_ci RETURN_IF_FAIL( 361cb0ef41Sopenharmony_ci UnboxULong64(boxed_instruction_offset.Get(), &instruction_offset)); 371cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostSymbols> symbols; 381cb0ef41Sopenharmony_ci RETURN_IF_FAIL(sp_debug_host.As(&symbols)); 391cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostContext> host_context; 401cb0ef41Sopenharmony_ci RETURN_IF_FAIL(sp_debug_host->GetCurrentContext(&host_context)); 411cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostModule> module; 421cb0ef41Sopenharmony_ci if (SUCCEEDED(symbols->FindModuleByLocation(host_context.Get(), 431cb0ef41Sopenharmony_ci instruction_offset, &module))) { 441cb0ef41Sopenharmony_ci Location module_base; 451cb0ef41Sopenharmony_ci RETURN_IF_FAIL(module->GetBaseLocation(&module_base)); 461cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostModule> v8_module = 471cb0ef41Sopenharmony_ci Extension::Current()->GetV8Module(host_context); 481cb0ef41Sopenharmony_ci if (v8_module == nullptr) { 491cb0ef41Sopenharmony_ci // Anything in a module must not be in the V8 module if the V8 module 501cb0ef41Sopenharmony_ci // doesn't exist. 511cb0ef41Sopenharmony_ci return original_hr; 521cb0ef41Sopenharmony_ci } 531cb0ef41Sopenharmony_ci Location v8_base; 541cb0ef41Sopenharmony_ci RETURN_IF_FAIL(v8_module->GetBaseLocation(&v8_base)); 551cb0ef41Sopenharmony_ci if (module_base != v8_base) { 561cb0ef41Sopenharmony_ci // It's in a module, but not the one that contains V8. 571cb0ef41Sopenharmony_ci return original_hr; 581cb0ef41Sopenharmony_ci } 591cb0ef41Sopenharmony_ci } 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci // Initialize an empty result object. 621cb0ef41Sopenharmony_ci WRL::ComPtr<IModelObject> result; 631cb0ef41Sopenharmony_ci RETURN_IF_FAIL(sp_data_model_manager->CreateSyntheticObject( 641cb0ef41Sopenharmony_ci host_context.Get(), &result)); 651cb0ef41Sopenharmony_ci WRL::ComPtr<IModelObject> parent_model; 661cb0ef41Sopenharmony_ci RETURN_IF_FAIL(sp_data_model_manager->AcquireNamedModel( 671cb0ef41Sopenharmony_ci is_parameters_ ? L"Debugger.Models.Parameters" 681cb0ef41Sopenharmony_ci : L"Debugger.Models.LocalVariables", 691cb0ef41Sopenharmony_ci &parent_model)); 701cb0ef41Sopenharmony_ci RETURN_IF_FAIL(result->AddParentModel(parent_model.Get(), /*context=*/nullptr, 711cb0ef41Sopenharmony_ci /*override=*/false)); 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci if (is_parameters_) { 741cb0ef41Sopenharmony_ci // We're not actually adding any parameters data yet; we just need it to not 751cb0ef41Sopenharmony_ci // fail so that the locals pane displays the LocalVariables. The locals pane 761cb0ef41Sopenharmony_ci // displays nothing if getting either LocalVariables or Parameters fails. 771cb0ef41Sopenharmony_ci *value = result.Detach(); 781cb0ef41Sopenharmony_ci return S_OK; 791cb0ef41Sopenharmony_ci } 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci // Get the stack and frame pointers for the current frame. 821cb0ef41Sopenharmony_ci WRL::ComPtr<IModelObject> boxed_stack_offset; 831cb0ef41Sopenharmony_ci RETURN_IF_FAIL( 841cb0ef41Sopenharmony_ci attributes->GetKeyValue(L"StackOffset", &boxed_stack_offset, nullptr)); 851cb0ef41Sopenharmony_ci ULONG64 stack_offset{}; 861cb0ef41Sopenharmony_ci RETURN_IF_FAIL(UnboxULong64(boxed_stack_offset.Get(), &stack_offset)); 871cb0ef41Sopenharmony_ci WRL::ComPtr<IModelObject> boxed_frame_offset; 881cb0ef41Sopenharmony_ci RETURN_IF_FAIL( 891cb0ef41Sopenharmony_ci attributes->GetKeyValue(L"FrameOffset", &boxed_frame_offset, nullptr)); 901cb0ef41Sopenharmony_ci ULONG64 frame_offset{}; 911cb0ef41Sopenharmony_ci RETURN_IF_FAIL(UnboxULong64(boxed_frame_offset.Get(), &frame_offset)); 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci // Eventually v8_debug_helper will provide some help here, but for now, just 941cb0ef41Sopenharmony_ci // provide the option to view the whole stack frame as tagged data. It can 951cb0ef41Sopenharmony_ci // be somewhat useful. 961cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostType> object_type = 971cb0ef41Sopenharmony_ci Extension::Current()->GetV8ObjectType(host_context); 981cb0ef41Sopenharmony_ci if (object_type == nullptr) { 991cb0ef41Sopenharmony_ci // There's nothing useful to do if we can't find the symbol for 1001cb0ef41Sopenharmony_ci // v8::internal::Object. 1011cb0ef41Sopenharmony_ci return original_hr; 1021cb0ef41Sopenharmony_ci } 1031cb0ef41Sopenharmony_ci ULONG64 object_size{}; 1041cb0ef41Sopenharmony_ci RETURN_IF_FAIL(object_type->GetSize(&object_size)); 1051cb0ef41Sopenharmony_ci ULONG64 num_objects = (frame_offset - stack_offset) / object_size; 1061cb0ef41Sopenharmony_ci ArrayDimension dimensions[] = { 1071cb0ef41Sopenharmony_ci {/*start=*/0, /*length=*/num_objects, /*stride=*/object_size}}; 1081cb0ef41Sopenharmony_ci WRL::ComPtr<IDebugHostType> object_array_type; 1091cb0ef41Sopenharmony_ci RETURN_IF_FAIL(object_type->CreateArrayOf(/*dimensions=*/1, dimensions, 1101cb0ef41Sopenharmony_ci &object_array_type)); 1111cb0ef41Sopenharmony_ci WRL::ComPtr<IModelObject> array; 1121cb0ef41Sopenharmony_ci RETURN_IF_FAIL(sp_data_model_manager->CreateTypedObject( 1131cb0ef41Sopenharmony_ci host_context.Get(), stack_offset, object_array_type.Get(), &array)); 1141cb0ef41Sopenharmony_ci RETURN_IF_FAIL( 1151cb0ef41Sopenharmony_ci result->SetKey(L"memory interpreted as Objects", array.Get(), nullptr)); 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ci std::vector<Property> properties = GetStackFrame(host_context, frame_offset); 1181cb0ef41Sopenharmony_ci for (const auto& prop : properties) { 1191cb0ef41Sopenharmony_ci WRL::ComPtr<IModelObject> property; 1201cb0ef41Sopenharmony_ci RETURN_IF_FAIL(GetModelForProperty(prop, host_context, &property)); 1211cb0ef41Sopenharmony_ci result->SetKey(reinterpret_cast<const wchar_t*>(prop.name.c_str()), 1221cb0ef41Sopenharmony_ci property.Get(), nullptr); 1231cb0ef41Sopenharmony_ci } 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ci *value = result.Detach(); 1261cb0ef41Sopenharmony_ci return S_OK; 1271cb0ef41Sopenharmony_ci} 1281cb0ef41Sopenharmony_ci 1291cb0ef41Sopenharmony_ciIFACEMETHODIMP V8LocalVariables::SetValue(PCWSTR key, IModelObject* context, 1301cb0ef41Sopenharmony_ci IModelObject* value) noexcept { 1311cb0ef41Sopenharmony_ci return E_NOTIMPL; 1321cb0ef41Sopenharmony_ci} 133