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
20 namespace d = v8::debug_helper;
21
22 namespace v8 {
23 namespace internal {
24 namespace debug_helper_internal {
25
26 // A value that was read from the debuggee's memory.
27 template <typename TValue>
28 struct Value {
29 d::MemoryAccessResult validity;
30 TValue value;
31 };
32
33 // Internal version of API class v8::debug_helper::PropertyBase.
34 class PropertyBase {
35 public:
PropertyBase(std::string name,std::string type,std::string decompressed_type)36 PropertyBase(std::string name, std::string type,
37 std::string decompressed_type)
38 : name_(name), type_(type), decompressed_type_(decompressed_type) {}
SetFieldsOnPublicView(d::PropertyBase * public_view)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.
52 class StructProperty : public PropertyBase {
53 public:
StructProperty(std::string name,std::string type,std::string decompressed_type,size_t offset,uint8_t num_bits,uint8_t shift_bits)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
GetPublicView()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.
80 class ObjectProperty : public PropertyBase {
81 public:
ObjectProperty(std::string name,std::string type,std::string decompressed_type,uintptr_t address,size_t num_values,size_t size,std::vector<std::unique_ptr<StructProperty>> struct_fields,d::PropertyKind kind)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
GetPublicView()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
121 class ObjectPropertiesResult;
122 struct 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.
128 class ObjectPropertiesResult {
129 public:
ObjectPropertiesResult(d::TypeCheckResult type_check_result,std::string brief,std::string type)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) {}
ObjectPropertiesResult(d::TypeCheckResult type_check_result,std::string brief,std::string type,std::vector<std::unique_ptr<ObjectProperty>> properties,std::vector<std::string> guessed_types)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
Prepend(const char * prefix)142 void Prepend(const char* prefix) { brief_ = prefix + brief_; }
143
GetPublicView()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
176 class StackFrameResult;
177 struct 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.
183 class StackFrameResult {
184 public:
StackFrameResult(std::vector<std::unique_ptr<ObjectProperty>> properties)185 StackFrameResult(std::vector<std::unique_ptr<ObjectProperty>> properties) {
186 properties_ = std::move(properties);
187 }
188
GetPublicView()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
207 class 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.
211 class TqObject {
212 public:
TqObject(uintptr_t address)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.
228 template <typename T>
CheckTypeName(const char * name)229 const 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.
236 bool 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.
240 uintptr_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.
245 d::PropertyKind GetArrayKind(d::MemoryAccessResult mem_result);
246
247 // List of fully-qualified names for every Object subtype, generated based on
248 // Torque class definitions.
249 extern const d::ClassList kObjectClassList;
250
251 } // namespace debug_helper_internal
252 } // namespace internal
253 } // namespace v8
254
255 #endif
256