1// Copyright 2019 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// This file defines internal versions of the public API structs. These should
6// all be tidy and simple classes which maintain proper ownership (unique_ptr)
7// of each other. Each contains an instance of its corresponding public type,
8// which can be filled out with GetPublicView.
9
10#ifndef V8_TOOLS_DEBUG_HELPER_DEBUG_HELPER_INTERNAL_H_
11#define V8_TOOLS_DEBUG_HELPER_DEBUG_HELPER_INTERNAL_H_
12
13#include <memory>
14#include <string>
15#include <vector>
16
17#include "debug-helper.h"
18#include "src/objects/instance-type.h"
19
20namespace d = v8::debug_helper;
21
22namespace v8 {
23namespace internal {
24namespace debug_helper_internal {
25
26// A value that was read from the debuggee's memory.
27template <typename TValue>
28struct Value {
29  d::MemoryAccessResult validity;
30  TValue value;
31};
32
33// Internal version of API class v8::debug_helper::PropertyBase.
34class PropertyBase {
35 public:
36  PropertyBase(std::string name, std::string type,
37               std::string decompressed_type)
38      : name_(name), type_(type), decompressed_type_(decompressed_type) {}
39  void SetFieldsOnPublicView(d::PropertyBase* public_view) {
40    public_view->name = name_.c_str();
41    public_view->type = type_.c_str();
42    public_view->decompressed_type = decompressed_type_.c_str();
43  }
44
45 private:
46  std::string name_;
47  std::string type_;
48  std::string decompressed_type_;
49};
50
51// Internal version of API class v8::debug_helper::StructProperty.
52class StructProperty : public PropertyBase {
53 public:
54  StructProperty(std::string name, std::string type,
55                 std::string decompressed_type, size_t offset, uint8_t num_bits,
56                 uint8_t shift_bits)
57      : PropertyBase(std::move(name), std::move(type),
58                     std::move(decompressed_type)),
59        offset_(offset),
60        num_bits_(num_bits),
61        shift_bits_(shift_bits) {}
62
63  d::StructProperty* GetPublicView() {
64    PropertyBase::SetFieldsOnPublicView(&public_view_);
65    public_view_.offset = offset_;
66    public_view_.num_bits = num_bits_;
67    public_view_.shift_bits = shift_bits_;
68    return &public_view_;
69  }
70
71 private:
72  size_t offset_;
73  uint8_t num_bits_;
74  uint8_t shift_bits_;
75
76  d::StructProperty public_view_;
77};
78
79// Internal version of API class v8::debug_helper::ObjectProperty.
80class ObjectProperty : public PropertyBase {
81 public:
82  ObjectProperty(std::string name, std::string type,
83                 std::string decompressed_type, uintptr_t address,
84                 size_t num_values, size_t size,
85                 std::vector<std::unique_ptr<StructProperty>> struct_fields,
86                 d::PropertyKind kind)
87      : PropertyBase(std::move(name), std::move(type),
88                     std::move(decompressed_type)),
89        address_(address),
90        num_values_(num_values),
91        size_(size),
92        struct_fields_(std::move(struct_fields)),
93        kind_(kind) {}
94
95  d::ObjectProperty* GetPublicView() {
96    PropertyBase::SetFieldsOnPublicView(&public_view_);
97    public_view_.address = address_;
98    public_view_.num_values = num_values_;
99    public_view_.size = size_;
100    public_view_.num_struct_fields = struct_fields_.size();
101    struct_fields_raw_.clear();
102    for (const auto& property : struct_fields_) {
103      struct_fields_raw_.push_back(property->GetPublicView());
104    }
105    public_view_.struct_fields = struct_fields_raw_.data();
106    public_view_.kind = kind_;
107    return &public_view_;
108  }
109
110 private:
111  uintptr_t address_;
112  size_t num_values_;
113  size_t size_;
114  std::vector<std::unique_ptr<StructProperty>> struct_fields_;
115  d::PropertyKind kind_;
116
117  d::ObjectProperty public_view_;
118  std::vector<d::StructProperty*> struct_fields_raw_;
119};
120
121class ObjectPropertiesResult;
122struct ObjectPropertiesResultExtended : public d::ObjectPropertiesResult {
123  // Back reference for cleanup.
124  debug_helper_internal::ObjectPropertiesResult* base;
125};
126
127// Internal version of API class v8::debug_helper::ObjectPropertiesResult.
128class ObjectPropertiesResult {
129 public:
130  ObjectPropertiesResult(d::TypeCheckResult type_check_result,
131                         std::string brief, std::string type)
132      : type_check_result_(type_check_result), brief_(brief), type_(type) {}
133  ObjectPropertiesResult(
134      d::TypeCheckResult type_check_result, std::string brief, std::string type,
135      std::vector<std::unique_ptr<ObjectProperty>> properties,
136      std::vector<std::string> guessed_types)
137      : ObjectPropertiesResult(type_check_result, brief, type) {
138    properties_ = std::move(properties);
139    guessed_types_ = std::move(guessed_types);
140  }
141
142  void Prepend(const char* prefix) { brief_ = prefix + brief_; }
143
144  d::ObjectPropertiesResult* GetPublicView() {
145    public_view_.type_check_result = type_check_result_;
146    public_view_.brief = brief_.c_str();
147    public_view_.type = type_.c_str();
148    public_view_.num_properties = properties_.size();
149    properties_raw_.clear();
150    for (const auto& property : properties_) {
151      properties_raw_.push_back(property->GetPublicView());
152    }
153    public_view_.properties = properties_raw_.data();
154    public_view_.num_guessed_types = guessed_types_.size();
155    guessed_types_raw_.clear();
156    for (const auto& guess : guessed_types_) {
157      guessed_types_raw_.push_back(guess.c_str());
158    }
159    public_view_.guessed_types = guessed_types_raw_.data();
160    public_view_.base = this;
161    return &public_view_;
162  }
163
164 private:
165  d::TypeCheckResult type_check_result_;
166  std::string brief_;
167  std::string type_;
168  std::vector<std::unique_ptr<ObjectProperty>> properties_;
169  std::vector<std::string> guessed_types_;
170
171  ObjectPropertiesResultExtended public_view_;
172  std::vector<d::ObjectProperty*> properties_raw_;
173  std::vector<const char*> guessed_types_raw_;
174};
175
176class StackFrameResult;
177struct StackFrameResultExtended : public d::StackFrameResult {
178  // Back reference for cleanup.
179  debug_helper_internal::StackFrameResult* base;
180};
181
182// Internal version of API class v8::debug_helper::StackFrameResult.
183class StackFrameResult {
184 public:
185  StackFrameResult(std::vector<std::unique_ptr<ObjectProperty>> properties) {
186    properties_ = std::move(properties);
187  }
188
189  d::StackFrameResult* GetPublicView() {
190    public_view_.num_properties = properties_.size();
191    properties_raw_.clear();
192    for (const auto& property : properties_) {
193      properties_raw_.push_back(property->GetPublicView());
194    }
195    public_view_.properties = properties_raw_.data();
196    public_view_.base = this;
197    return &public_view_;
198  }
199
200 private:
201  std::vector<std::unique_ptr<ObjectProperty>> properties_;
202
203  StackFrameResultExtended public_view_;
204  std::vector<d::ObjectProperty*> properties_raw_;
205};
206
207class TqObjectVisitor;
208
209// Base class representing a V8 object in the debuggee's address space.
210// Subclasses for specific object types are generated by the Torque compiler.
211class TqObject {
212 public:
213  TqObject(uintptr_t address) : address_(address) {}
214  virtual ~TqObject() = default;
215  virtual std::vector<std::unique_ptr<ObjectProperty>> GetProperties(
216      d::MemoryAccessor accessor) const;
217  virtual const char* GetName() const;
218  virtual void Visit(TqObjectVisitor* visitor) const;
219  virtual bool IsSuperclassOf(const TqObject* other) const;
220
221 protected:
222  uintptr_t address_;
223};
224
225// A helpful template so that generated code can be sure that a string type name
226// actually resolves to a type, by repeating the name as the template parameter
227// and the value.
228template <typename T>
229const char* CheckTypeName(const char* name) {
230  return name;
231}
232
233// In ptr-compr builds, returns whether the address looks like a compressed
234// pointer (zero-extended from 32 bits). Otherwise returns false because no
235// pointers can be compressed.
236bool IsPointerCompressed(uintptr_t address);
237
238// If the given address looks like a compressed pointer, returns a decompressed
239// representation of it. Otherwise returns the address unmodified.
240uintptr_t EnsureDecompressed(uintptr_t address,
241                             uintptr_t any_uncompressed_address);
242
243// Converts the MemoryAccessResult from attempting to read an array's length
244// into the corresponding PropertyKind for the array.
245d::PropertyKind GetArrayKind(d::MemoryAccessResult mem_result);
246
247// List of fully-qualified names for every Object subtype, generated based on
248// Torque class definitions.
249extern const d::ClassList kObjectClassList;
250
251}  // namespace debug_helper_internal
252}  // namespace internal
253}  // namespace v8
254
255#endif
256