blob: 78dcd5ef2cb9995eed34fc4d08405cacbb0c903a [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_DEVELOPER_DEBUG_ZXDB_EXPR_VIRTUAL_BASE_TEST_SETUP_H_
#define SRC_DEVELOPER_DEBUG_ZXDB_EXPR_VIRTUAL_BASE_TEST_SETUP_H_
#include <memory>
#include <vector>
#include "src/developer/debug/zxdb/symbols/arch.h"
#include "src/developer/debug/zxdb/symbols/collection.h"
#include "src/developer/debug/zxdb/symbols/elf_symbol.h"
#include "src/developer/debug/zxdb/symbols/index_test_support.h"
#include "src/developer/debug/zxdb/symbols/process_symbols_test_setup.h"
#include "src/developer/debug/zxdb/symbols/symbol.h"
namespace zxdb {
class MockModuleSymbols;
class MockSymbolDataProvider;
struct TestIndexedSymbol;
// Sets up the required information for a test involving a base class with a virtual function and
// a class derived from it. The necessary symbols for the vtables all need to be set properly.
//
// It is designed to work with a module loaded at the address provided by ProcessSymbolsTestSetup.
//
// Example:
//
// VirtualBaseTestSetup setup(...);
// ExprValue ptr(setup::kBaseAddress, setup.base_class_ptr);
//
// This will be a pointer to the Base class that is actually implemented by the Derived class.
struct VirtualBaseTestSetup {
VirtualBaseTestSetup(MockSymbolDataProvider* data_provider,
MockModuleSymbols* mock_module_symbols);
// Clang uses "vtbl_ptr_type*" as the type for the vtable pointers at the beginning of a virtual
// class. Clang defines the vtable as being pointers to functions "int()", so a pointer to a table
// is a pointer to that. For simplicity, we define the vtable entry type as uint64_t instead of
// "int()".
fxl::RefPtr<Type> vtbl_entry_type;
fxl::RefPtr<Type> vtbl_ptr_type;
fxl::RefPtr<Type> vtbl_ptr_type_ptr;
// Virtual base class collection type. It has one member "base_i" = kBaseI defined below.
fxl::RefPtr<Collection> base_class;
std::unique_ptr<TestIndexedSymbol> base_class_indexed;
fxl::RefPtr<ModifiedType> base_class_ptr; // BaseClass*
fxl::RefPtr<ModifiedType> base_class_ref; // BaseClass&
// This starts the base class at an offset inside of the derived one, leaving empty bytes at the
// beginning. This simulates having multiple inheritance and tests the offset management.
static constexpr uint32_t kBaseOffset = 4;
// Derived class type. It has one member "derived_i" = kDerivedI defined below.
fxl::RefPtr<Collection> derived_class;
std::unique_ptr<TestIndexedSymbol> derived_class_indexed;
// Address of the derived class' vtable.
static constexpr TargetPointer kVtableRelativeAddress = 0x2000;
static constexpr TargetPointer kVtableAbsoluteAddress =
ProcessSymbolsTestSetup::kDefaultLoadAddress + kVtableRelativeAddress;
// Absolute address of the derived and base class in memory.
static constexpr TargetPointer kDerivedAddress = 0x1000;
static constexpr TargetPointer kBaseAddress = kDerivedAddress + kBaseOffset;
// Symbols for the vtables. Make kVtableAddress can point to one of these to determine the type of
// the class.
fxl::RefPtr<ElfSymbol> base_vtable;
fxl::RefPtr<ElfSymbol> derived_vtable;
// The values of the two data members in the derived_data.
static const char* kBaseIName; // member name = "base_i".
static constexpr uint32_t kBaseI = 42;
static const char* kDerivedIName; // member name = "derived_i".
static constexpr uint32_t kDerivedI = 99;
// Sample data for the derived class. This will have a vtable address of kVtableAddress and
// will be injected into the mock eval context at kDerivedAddress.
std::vector<uint8_t> derived_data;
};
} // namespace zxdb
#endif // SRC_DEVELOPER_DEBUG_ZXDB_EXPR_VIRTUAL_BASE_TEST_SETUP_H_