1d3c4975be
If we can read an object's Map pointer but not any data from the Map itself, we may still be able to accurately describe the object's type if the Map pointer matches one of the known Maps from the snapshot. GetObjectProperties uses that data in one of two ways: - If it is sure that the Map pointer matches a known Map, then it uses the type from that Map and continues as if it read the type normally. - If the Map pointer is at the right offset within a heap page to match a known Map, but the caller didn't provide the addresses of the first pages in Map space or read-only space, then the type of that Map is just a guess and gets returned in a separate array. This gives the caller the opportunity to present guessed types to the user, and perhaps call again using the guessed type as the type hint. Bug: v8:9376 Change-Id: I187f67b77e76699863a14534a9d635b79f654124 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1787986 Commit-Queue: Seth Brenith <seth.brenith@microsoft.com> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Reviewed-by: Michael Achenbach <machenbach@chromium.org> Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Cr-Commit-Position: refs/heads/master@{#63908}
157 lines
5.3 KiB
C++
157 lines
5.3 KiB
C++
// Copyright 2019 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
// This file defines internal versions of the public API structs. These should
|
|
// all be tidy and simple classes which maintain proper ownership (unique_ptr)
|
|
// of each other. Each contains an instance of its corresponding public type,
|
|
// which can be filled out with GetPublicView.
|
|
|
|
#ifndef V8_TOOLS_DEBUG_HELPER_DEBUG_HELPER_INTERNAL_H_
|
|
#define V8_TOOLS_DEBUG_HELPER_DEBUG_HELPER_INTERNAL_H_
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "debug-helper.h"
|
|
#include "src/objects/instance-type.h"
|
|
|
|
namespace d = v8::debug_helper;
|
|
|
|
namespace v8_debug_helper_internal {
|
|
|
|
// A value that was read from the debuggee's memory.
|
|
template <typename TValue>
|
|
struct Value {
|
|
d::MemoryAccessResult validity;
|
|
TValue value;
|
|
};
|
|
|
|
// Internal version of API class v8::debug_helper::ObjectProperty.
|
|
class ObjectProperty {
|
|
public:
|
|
inline ObjectProperty(std::string name, std::string type,
|
|
std::string decompressed_type, uintptr_t address,
|
|
size_t num_values = 1,
|
|
d::PropertyKind kind = d::PropertyKind::kSingle)
|
|
: name_(name),
|
|
type_(type),
|
|
decompressed_type_(decompressed_type),
|
|
address_(address),
|
|
num_values_(num_values),
|
|
kind_(kind) {}
|
|
|
|
inline d::ObjectProperty* GetPublicView() {
|
|
public_view_.name = name_.c_str();
|
|
public_view_.type = type_.c_str();
|
|
public_view_.decompressed_type = decompressed_type_.c_str();
|
|
public_view_.address = address_;
|
|
public_view_.num_values = num_values_;
|
|
public_view_.kind = kind_;
|
|
return &public_view_;
|
|
}
|
|
|
|
private:
|
|
std::string name_;
|
|
std::string type_;
|
|
std::string decompressed_type_;
|
|
uintptr_t address_;
|
|
size_t num_values_;
|
|
d::PropertyKind kind_;
|
|
|
|
d::ObjectProperty public_view_;
|
|
};
|
|
|
|
class ObjectPropertiesResult;
|
|
using ObjectPropertiesResultInternal = ObjectPropertiesResult;
|
|
|
|
struct ObjectPropertiesResultExtended : public d::ObjectPropertiesResult {
|
|
ObjectPropertiesResultInternal* base; // Back reference for cleanup
|
|
};
|
|
|
|
// Internal version of API class v8::debug_helper::ObjectPropertiesResult.
|
|
class ObjectPropertiesResult {
|
|
public:
|
|
ObjectPropertiesResult(d::TypeCheckResult type_check_result,
|
|
std::string brief, std::string type)
|
|
: 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)
|
|
: ObjectPropertiesResult(type_check_result, brief, type) {
|
|
properties_ = std::move(properties);
|
|
guessed_types_ = std::move(guessed_types);
|
|
}
|
|
|
|
inline void Prepend(const char* prefix) { brief_ = prefix + brief_; }
|
|
|
|
inline d::ObjectPropertiesResult* GetPublicView() {
|
|
public_view_.type_check_result = type_check_result_;
|
|
public_view_.brief = brief_.c_str();
|
|
public_view_.type = type_.c_str();
|
|
public_view_.num_properties = properties_.size();
|
|
properties_raw_.clear();
|
|
for (const auto& property : properties_) {
|
|
properties_raw_.push_back(property->GetPublicView());
|
|
}
|
|
public_view_.properties = properties_raw_.data();
|
|
public_view_.num_guessed_types = guessed_types_.size();
|
|
guessed_types_raw_.clear();
|
|
for (const auto& guess : guessed_types_) {
|
|
guessed_types_raw_.push_back(guess.c_str());
|
|
}
|
|
public_view_.guessed_types = guessed_types_raw_.data();
|
|
public_view_.base = this;
|
|
return &public_view_;
|
|
}
|
|
|
|
private:
|
|
d::TypeCheckResult type_check_result_;
|
|
std::string brief_;
|
|
std::string type_;
|
|
std::vector<std::unique_ptr<ObjectProperty>> properties_;
|
|
std::vector<std::string> guessed_types_;
|
|
|
|
ObjectPropertiesResultExtended public_view_;
|
|
std::vector<d::ObjectProperty*> properties_raw_;
|
|
std::vector<const char*> guessed_types_raw_;
|
|
};
|
|
|
|
class TqObjectVisitor;
|
|
|
|
// Base class representing a V8 object in the debuggee's address space.
|
|
// Subclasses for specific object types are generated by the Torque compiler.
|
|
class TqObject {
|
|
public:
|
|
inline TqObject(uintptr_t address) : address_(address) {}
|
|
virtual ~TqObject() = default;
|
|
virtual std::vector<std::unique_ptr<ObjectProperty>> GetProperties(
|
|
d::MemoryAccessor accessor) const;
|
|
virtual const char* GetName() const;
|
|
virtual void Visit(TqObjectVisitor* visitor) const;
|
|
virtual bool IsSuperclassOf(const TqObject* other) const;
|
|
|
|
protected:
|
|
uintptr_t address_;
|
|
};
|
|
|
|
// In ptr-compr builds, returns whether the address looks like a compressed
|
|
// pointer (sign-extended from 32 bits). Otherwise returns false because no
|
|
// pointers can be compressed.
|
|
bool IsPointerCompressed(uintptr_t address);
|
|
|
|
// If the given address looks like a compressed pointer, returns a decompressed
|
|
// representation of it. Otherwise returns the address unmodified.
|
|
uintptr_t EnsureDecompressed(uintptr_t address,
|
|
uintptr_t any_uncompressed_address);
|
|
|
|
// Converts the MemoryAccessResult from attempting to read an array's length
|
|
// into the corresponding PropertyKind for the array.
|
|
d::PropertyKind GetArrayKind(d::MemoryAccessResult mem_result);
|
|
|
|
} // namespace v8_debug_helper_internal
|
|
|
|
#endif
|