Coverage Report

Created: 2022-01-25 06:29

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- BlockPointer.cpp --------------------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "BlockPointer.h"
10
11
#include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"
12
#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
13
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
14
#include "lldb/Core/ValueObject.h"
15
#include "lldb/DataFormatters/FormattersHelpers.h"
16
#include "lldb/Symbol/CompilerType.h"
17
#include "lldb/Symbol/TypeSystem.h"
18
#include "lldb/Target/Target.h"
19
#include "lldb/Utility/LLDBAssert.h"
20
#include "lldb/Utility/Log.h"
21
22
using namespace lldb;
23
using namespace lldb_private;
24
using namespace lldb_private::formatters;
25
26
namespace lldb_private {
27
namespace formatters {
28
29
class BlockPointerSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
30
public:
31
  BlockPointerSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
32
12
      : SyntheticChildrenFrontEnd(*valobj_sp), m_block_struct_type() {
33
12
    CompilerType block_pointer_type(m_backend.GetCompilerType());
34
12
    CompilerType function_pointer_type;
35
12
    block_pointer_type.IsBlockPointerType(&function_pointer_type);
36
37
12
    TargetSP target_sp(m_backend.GetTargetSP());
38
39
12
    if (!target_sp) {
40
0
      return;
41
0
    }
42
43
12
    auto type_system_or_err = target_sp->GetScratchTypeSystemForLanguage(
44
12
        lldb::eLanguageTypeC_plus_plus);
45
12
    if (auto err = type_system_or_err.takeError()) {
46
0
      LLDB_LOG_ERROR(
47
0
          lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS),
48
0
          std::move(err), "Failed to get scratch TypeSystemClang");
49
0
      return;
50
0
    }
51
52
12
    TypeSystemClang *clang_ast_context =
53
12
        llvm::cast<TypeSystemClang>(block_pointer_type.GetTypeSystem());
54
55
12
    std::shared_ptr<ClangASTImporter> clang_ast_importer;
56
12
    auto *state = target_sp->GetPersistentExpressionStateForLanguage(
57
12
        lldb::eLanguageTypeC_plus_plus);
58
12
    if (state) {
59
12
      auto *persistent_vars = llvm::cast<ClangPersistentVariables>(state);
60
12
      clang_ast_importer = persistent_vars->GetClangASTImporter();
61
12
    }
62
63
12
    if (!clang_ast_importer) {
64
0
      return;
65
0
    }
66
67
12
    const char *const isa_name("__isa");
68
12
    const CompilerType isa_type =
69
12
        clang_ast_context->GetBasicType(lldb::eBasicTypeObjCClass);
70
12
    const char *const flags_name("__flags");
71
12
    const CompilerType flags_type =
72
12
        clang_ast_context->GetBasicType(lldb::eBasicTypeInt);
73
12
    const char *const reserved_name("__reserved");
74
12
    const CompilerType reserved_type =
75
12
        clang_ast_context->GetBasicType(lldb::eBasicTypeInt);
76
12
    const char *const FuncPtr_name("__FuncPtr");
77
78
12
    m_block_struct_type = clang_ast_context->CreateStructForIdentifier(
79
12
        ConstString(), {{isa_name, isa_type},
80
12
                        {flags_name, flags_type},
81
12
                        {reserved_name, reserved_type},
82
12
                        {FuncPtr_name, function_pointer_type}});
83
12
  }
84
85
6
  ~BlockPointerSyntheticFrontEnd() override = default;
86
87
6
  size_t CalculateNumChildren() override {
88
6
    const bool omit_empty_base_classes = false;
89
6
    return m_block_struct_type.GetNumChildren(omit_empty_base_classes, nullptr);
90
6
  }
91
92
6
  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
93
6
    if (!m_block_struct_type.IsValid()) {
94
0
      return lldb::ValueObjectSP();
95
0
    }
96
97
6
    if (idx >= CalculateNumChildren()) {
98
0
      return lldb::ValueObjectSP();
99
0
    }
100
101
6
    const bool thread_and_frame_only_if_stopped = true;
102
6
    ExecutionContext exe_ctx = m_backend.GetExecutionContextRef().Lock(
103
6
        thread_and_frame_only_if_stopped);
104
6
    const bool transparent_pointers = false;
105
6
    const bool omit_empty_base_classes = false;
106
6
    const bool ignore_array_bounds = false;
107
6
    ValueObject *value_object = nullptr;
108
109
6
    std::string child_name;
110
6
    uint32_t child_byte_size = 0;
111
6
    int32_t child_byte_offset = 0;
112
6
    uint32_t child_bitfield_bit_size = 0;
113
6
    uint32_t child_bitfield_bit_offset = 0;
114
6
    bool child_is_base_class = false;
115
6
    bool child_is_deref_of_parent = false;
116
6
    uint64_t language_flags = 0;
117
118
6
    const CompilerType child_type =
119
6
        m_block_struct_type.GetChildCompilerTypeAtIndex(
120
6
            &exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
121
6
            ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
122
6
            child_bitfield_bit_size, child_bitfield_bit_offset,
123
6
            child_is_base_class, child_is_deref_of_parent, value_object,
124
6
            language_flags);
125
126
6
    ValueObjectSP struct_pointer_sp =
127
6
        m_backend.Cast(m_block_struct_type.GetPointerType());
128
129
6
    if (!struct_pointer_sp) {
130
0
      return lldb::ValueObjectSP();
131
0
    }
132
133
6
    Status err;
134
6
    ValueObjectSP struct_sp = struct_pointer_sp->Dereference(err);
135
136
6
    if (!struct_sp || !err.Success()) {
137
0
      return lldb::ValueObjectSP();
138
0
    }
139
140
6
    ValueObjectSP child_sp(struct_sp->GetSyntheticChildAtOffset(
141
6
        child_byte_offset, child_type, true,
142
6
        ConstString(child_name.c_str(), child_name.size())));
143
144
6
    return child_sp;
145
6
  }
146
147
  // return true if this object is now safe to use forever without ever
148
  // updating again; the typical (and tested) answer here is 'false'
149
12
  bool Update() override { return false; }
150
151
  // maybe return false if the block pointer is, say, null
152
0
  bool MightHaveChildren() override { return true; }
153
154
6
  size_t GetIndexOfChildWithName(ConstString name) override {
155
6
    if (!m_block_struct_type.IsValid())
156
0
      return UINT32_MAX;
157
158
6
    const bool omit_empty_base_classes = false;
159
6
    return m_block_struct_type.GetIndexOfChildWithName(name.AsCString(),
160
6
                                                       omit_empty_base_classes);
161
6
  }
162
163
private:
164
  CompilerType m_block_struct_type;
165
};
166
167
} // namespace formatters
168
} // namespace lldb_private
169
170
bool lldb_private::formatters::BlockPointerSummaryProvider(
171
6
    ValueObject &valobj, Stream &s, const TypeSummaryOptions &) {
172
6
  lldb_private::SyntheticChildrenFrontEnd *synthetic_children =
173
6
      BlockPointerSyntheticFrontEndCreator(nullptr, valobj.GetSP());
174
6
  if (!synthetic_children) {
175
0
    return false;
176
0
  }
177
178
6
  synthetic_children->Update();
179
180
6
  static const ConstString s_FuncPtr_name("__FuncPtr");
181
182
6
  lldb::ValueObjectSP child_sp = synthetic_children->GetChildAtIndex(
183
6
      synthetic_children->GetIndexOfChildWithName(s_FuncPtr_name));
184
185
6
  if (!child_sp) {
186
0
    return false;
187
0
  }
188
189
6
  lldb::ValueObjectSP qualified_child_representation_sp =
190
6
      child_sp->GetQualifiedRepresentationIfAvailable(
191
6
          lldb::eDynamicDontRunTarget, true);
192
193
6
  const char *child_value =
194
6
      qualified_child_representation_sp->GetValueAsCString();
195
196
6
  s.Printf("%s", child_value);
197
198
6
  return true;
199
6
}
200
201
lldb_private::SyntheticChildrenFrontEnd *
202
lldb_private::formatters::BlockPointerSyntheticFrontEndCreator(
203
12
    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
204
12
  if (!valobj_sp)
205
0
    return nullptr;
206
12
  return new BlockPointerSyntheticFrontEnd(valobj_sp);
207
12
}