Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Core/ValueObjectDynamicValue.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- ValueObjectDynamicValue.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 "lldb/Core/ValueObjectDynamicValue.h"
10
#include "lldb/Core/Value.h"
11
#include "lldb/Core/ValueObject.h"
12
#include "lldb/Symbol/CompilerType.h"
13
#include "lldb/Symbol/Type.h"
14
#include "lldb/Target/ExecutionContext.h"
15
#include "lldb/Target/LanguageRuntime.h"
16
#include "lldb/Target/Process.h"
17
#include "lldb/Target/Target.h"
18
#include "lldb/Utility/DataExtractor.h"
19
#include "lldb/Utility/LLDBLog.h"
20
#include "lldb/Utility/Log.h"
21
#include "lldb/Utility/Scalar.h"
22
#include "lldb/Utility/Status.h"
23
#include "lldb/lldb-types.h"
24
25
#include <cstring>
26
#include <optional>
27
namespace lldb_private {
28
class Declaration;
29
}
30
31
using namespace lldb_private;
32
33
ValueObjectDynamicValue::ValueObjectDynamicValue(
34
    ValueObject &parent, lldb::DynamicValueType use_dynamic)
35
1.53k
    : ValueObject(parent), m_address(), m_dynamic_type_info(),
36
1.53k
      m_use_dynamic(use_dynamic) {
37
1.53k
  SetName(parent.GetName());
38
1.53k
}
39
40
32.9k
CompilerType ValueObjectDynamicValue::GetCompilerTypeImpl() {
41
32.9k
  const bool success = UpdateValueIfNeeded(false);
42
32.9k
  if (success) {
43
32.9k
    if (m_dynamic_type_info.HasType())
44
32.9k
      return m_value.GetCompilerType();
45
0
    else
46
0
      return m_parent->GetCompilerType();
47
32.9k
  }
48
0
  return m_parent->GetCompilerType();
49
32.9k
}
50
51
618
ConstString ValueObjectDynamicValue::GetTypeName() {
52
618
  const bool success = UpdateValueIfNeeded(false);
53
618
  if (success) {
54
618
    if (m_dynamic_type_info.HasName())
55
618
      return m_dynamic_type_info.GetName();
56
618
  }
57
0
  return m_parent->GetTypeName();
58
618
}
59
60
25
TypeImpl ValueObjectDynamicValue::GetTypeImpl() {
61
25
  const bool success = UpdateValueIfNeeded(false);
62
25
  if (success && m_type_impl.IsValid()) {
63
25
    return m_type_impl;
64
25
  }
65
0
  return m_parent->GetTypeImpl();
66
25
}
67
68
2.99k
ConstString ValueObjectDynamicValue::GetQualifiedTypeName() {
69
2.99k
  const bool success = UpdateValueIfNeeded(false);
70
2.99k
  if (success) {
71
2.99k
    if (m_dynamic_type_info.HasName())
72
2.99k
      return m_dynamic_type_info.GetName();
73
2.99k
  }
74
0
  return m_parent->GetQualifiedTypeName();
75
2.99k
}
76
77
395
ConstString ValueObjectDynamicValue::GetDisplayTypeName() {
78
395
  const bool success = UpdateValueIfNeeded(false);
79
395
  if (success) {
80
395
    if (m_dynamic_type_info.HasType())
81
395
      return GetCompilerType().GetDisplayTypeName();
82
0
    if (m_dynamic_type_info.HasName())
83
0
      return m_dynamic_type_info.GetName();
84
0
  }
85
0
  return m_parent->GetDisplayTypeName();
86
395
}
87
88
202
size_t ValueObjectDynamicValue::CalculateNumChildren(uint32_t max) {
89
202
  const bool success = UpdateValueIfNeeded(false);
90
202
  if (success && m_dynamic_type_info.HasType()) {
91
202
    ExecutionContext exe_ctx(GetExecutionContextRef());
92
202
    auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
93
202
    return children_count <= max ? children_count : 
max0
;
94
202
  } else
95
0
    return m_parent->GetNumChildren(max);
96
202
}
97
98
8
std::optional<uint64_t> ValueObjectDynamicValue::GetByteSize() {
99
8
  const bool success = UpdateValueIfNeeded(false);
100
8
  if (success && m_dynamic_type_info.HasType()) {
101
8
    ExecutionContext exe_ctx(GetExecutionContextRef());
102
8
    return m_value.GetValueByteSize(nullptr, &exe_ctx);
103
8
  } else
104
0
    return m_parent->GetByteSize();
105
8
}
106
107
8
lldb::ValueType ValueObjectDynamicValue::GetValueType() const {
108
8
  return m_parent->GetValueType();
109
8
}
110
111
1.59k
bool ValueObjectDynamicValue::UpdateValue() {
112
1.59k
  SetValueIsValid(false);
113
1.59k
  m_error.Clear();
114
115
1.59k
  if (!m_parent->UpdateValueIfNeeded(false)) {
116
    // The dynamic value failed to get an error, pass the error along
117
0
    if (m_error.Success() && m_parent->GetError().Fail())
118
0
      m_error = m_parent->GetError();
119
0
    return false;
120
0
  }
121
122
  // Setting our type_sp to NULL will route everything back through our parent
123
  // which is equivalent to not using dynamic values.
124
1.59k
  if (m_use_dynamic == lldb::eNoDynamicValues) {
125
0
    m_dynamic_type_info.Clear();
126
0
    return true;
127
0
  }
128
129
1.59k
  ExecutionContext exe_ctx(GetExecutionContextRef());
130
1.59k
  Target *target = exe_ctx.GetTargetPtr();
131
1.59k
  if (target) {
132
1.59k
    m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
133
1.59k
    m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
134
1.59k
  }
135
136
  // First make sure our Type and/or Address haven't changed:
137
1.59k
  Process *process = exe_ctx.GetProcessPtr();
138
1.59k
  if (!process)
139
0
    return false;
140
141
1.59k
  TypeAndOrName class_type_or_name;
142
1.59k
  Address dynamic_address;
143
1.59k
  bool found_dynamic_type = false;
144
1.59k
  Value::ValueType value_type;
145
146
1.59k
  LanguageRuntime *runtime = nullptr;
147
148
1.59k
  lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage();
149
1.59k
  if (known_type != lldb::eLanguageTypeUnknown &&
150
1.59k
      known_type != lldb::eLanguageTypeC) {
151
1.10k
    runtime = process->GetLanguageRuntime(known_type);
152
1.10k
    if (auto *preferred_runtime =
153
1.10k
            runtime->GetPreferredLanguageRuntime(*m_parent)) {
154
      // Try the preferred runtime first.
155
1.00k
      found_dynamic_type = preferred_runtime->GetDynamicTypeAndAddress(
156
1.00k
          *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
157
1.00k
          value_type);
158
1.00k
      if (found_dynamic_type)
159
        // Set the operative `runtime` for later use in this function.
160
1.00k
        runtime = preferred_runtime;
161
1.00k
    }
162
1.10k
    if (!found_dynamic_type)
163
      // Fallback to the runtime for `known_type`.
164
101
      found_dynamic_type = runtime->GetDynamicTypeAndAddress(
165
101
          *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
166
101
          value_type);
167
1.10k
  } else {
168
492
    runtime = process->GetLanguageRuntime(lldb::eLanguageTypeC_plus_plus);
169
492
    if (runtime)
170
492
      found_dynamic_type = runtime->GetDynamicTypeAndAddress(
171
492
          *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
172
492
          value_type);
173
174
492
    if (!found_dynamic_type) {
175
492
      runtime = process->GetLanguageRuntime(lldb::eLanguageTypeObjC);
176
492
      if (runtime)
177
491
        found_dynamic_type = runtime->GetDynamicTypeAndAddress(
178
491
            *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
179
491
            value_type);
180
492
    }
181
492
  }
182
183
  // Getting the dynamic value may have run the program a bit, and so marked us
184
  // as needing updating, but we really don't...
185
186
1.59k
  m_update_point.SetUpdated();
187
188
1.59k
  if (runtime && 
found_dynamic_type1.59k
) {
189
1.09k
    if (class_type_or_name.HasType()) {
190
1.09k
      m_type_impl =
191
1.09k
          TypeImpl(m_parent->GetCompilerType(),
192
1.09k
                   runtime->FixUpDynamicType(class_type_or_name, *m_parent)
193
1.09k
                       .GetCompilerType());
194
1.09k
    } else {
195
0
      m_type_impl.Clear();
196
0
    }
197
1.09k
  } else {
198
496
    m_type_impl.Clear();
199
496
  }
200
201
  // If we don't have a dynamic type, set ourselves to be invalid and return
202
  // false.  We used to try to produce a dynamic ValueObject that behaved "like"
203
  // its parent, but that failed for ValueObjectConstResult, which is too 
204
  // complex a beast to try to emulate.  If we return an invalid ValueObject,
205
  // clients will end up getting the static value instead, which behaves
206
  // correctly.
207
1.59k
  if (!found_dynamic_type) {
208
496
    if (m_dynamic_type_info)
209
4
      SetValueDidChange(true);
210
496
    ClearDynamicTypeInformation();
211
496
    m_dynamic_type_info.Clear();
212
496
    m_error.SetErrorString("no dynamic type found");
213
496
    return false;
214
496
  }
215
216
1.09k
  Value old_value(m_value);
217
218
1.09k
  Log *log = GetLog(LLDBLog::Types);
219
220
1.09k
  bool has_changed_type = false;
221
222
1.09k
  if (!m_dynamic_type_info) {
223
1.05k
    m_dynamic_type_info = class_type_or_name;
224
1.05k
    has_changed_type = true;
225
1.05k
  } else 
if (49
class_type_or_name != m_dynamic_type_info49
) {
226
    // We are another type, we need to tear down our children...
227
49
    m_dynamic_type_info = class_type_or_name;
228
49
    SetValueDidChange(true);
229
49
    has_changed_type = true;
230
49
  }
231
232
1.09k
  if (has_changed_type)
233
1.09k
    ClearDynamicTypeInformation();
234
235
1.09k
  if (!m_address.IsValid() || 
m_address != dynamic_address49
) {
236
1.05k
    if (m_address.IsValid())
237
0
      SetValueDidChange(true);
238
239
    // We've moved, so we should be fine...
240
1.05k
    m_address = dynamic_address;
241
1.05k
    lldb::TargetSP target_sp(GetTargetSP());
242
1.05k
    lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
243
1.05k
    m_value.GetScalar() = load_address;
244
1.05k
  }
245
246
1.09k
  if (runtime)
247
1.09k
    m_dynamic_type_info =
248
1.09k
        runtime->FixUpDynamicType(m_dynamic_type_info, *m_parent);
249
250
1.09k
  m_value.SetCompilerType(m_dynamic_type_info.GetCompilerType());
251
252
1.09k
  m_value.SetValueType(value_type);
253
254
1.09k
  if (has_changed_type && log)
255
0
    LLDB_LOGF(log, "[%s %p] has a new dynamic type %s", GetName().GetCString(),
256
1.09k
              static_cast<void *>(this), GetTypeName().GetCString());
257
258
1.09k
  if (m_address.IsValid() && m_dynamic_type_info) {
259
    // The variable value is in the Scalar value inside the m_value. We can
260
    // point our m_data right to it.
261
1.09k
    m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
262
1.09k
    if (m_error.Success()) {
263
1.09k
      if (!CanProvideValue()) {
264
        // this value object represents an aggregate type whose children have
265
        // values, but this object does not. So we say we are changed if our
266
        // location has changed.
267
0
        SetValueDidChange(m_value.GetValueType() != old_value.GetValueType() ||
268
0
                          m_value.GetScalar() != old_value.GetScalar());
269
0
      }
270
271
1.09k
      SetValueIsValid(true);
272
1.09k
      return true;
273
1.09k
    }
274
1.09k
  }
275
276
  // We get here if we've failed above...
277
0
  SetValueIsValid(false);
278
0
  return false;
279
1.09k
}
280
281
2.26k
bool ValueObjectDynamicValue::IsInScope() { return m_parent->IsInScope(); }
282
283
bool ValueObjectDynamicValue::SetValueFromCString(const char *value_str,
284
2
                                                  Status &error) {
285
2
  if (!UpdateValueIfNeeded(false)) {
286
0
    error.SetErrorString("unable to read value");
287
0
    return false;
288
0
  }
289
290
2
  uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
291
2
  uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
292
293
2
  if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
294
0
    error.SetErrorString("unable to read value");
295
0
    return false;
296
0
  }
297
298
  // if we are at an offset from our parent, in order to set ourselves
299
  // correctly we would need to change the new value so that it refers to the
300
  // correct dynamic type. we choose not to deal with that - if anything more
301
  // than a value overwrite is required, you should be using the expression
302
  // parser instead of the value editing facility
303
2
  if (my_value != parent_value) {
304
    // but NULL'ing out a value should always be allowed
305
0
    if (strcmp(value_str, "0")) {
306
0
      error.SetErrorString(
307
0
          "unable to modify dynamic value, use 'expression' command");
308
0
      return false;
309
0
    }
310
0
  }
311
312
2
  bool ret_val = m_parent->SetValueFromCString(value_str, error);
313
2
  SetNeedsUpdate();
314
2
  return ret_val;
315
2
}
316
317
2
bool ValueObjectDynamicValue::SetData(DataExtractor &data, Status &error) {
318
2
  if (!UpdateValueIfNeeded(false)) {
319
0
    error.SetErrorString("unable to read value");
320
0
    return false;
321
0
  }
322
323
2
  uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
324
2
  uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
325
326
2
  if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
327
0
    error.SetErrorString("unable to read value");
328
0
    return false;
329
0
  }
330
331
  // if we are at an offset from our parent, in order to set ourselves
332
  // correctly we would need to change the new value so that it refers to the
333
  // correct dynamic type. we choose not to deal with that - if anything more
334
  // than a value overwrite is required, you should be using the expression
335
  // parser instead of the value editing facility
336
2
  if (my_value != parent_value) {
337
    // but NULL'ing out a value should always be allowed
338
0
    lldb::offset_t offset = 0;
339
340
0
    if (data.GetAddress(&offset) != 0) {
341
0
      error.SetErrorString(
342
0
          "unable to modify dynamic value, use 'expression' command");
343
0
      return false;
344
0
    }
345
0
  }
346
347
2
  bool ret_val = m_parent->SetData(data, error);
348
2
  SetNeedsUpdate();
349
2
  return ret_val;
350
2
}
351
352
void ValueObjectDynamicValue::SetPreferredDisplayLanguage(
353
0
    lldb::LanguageType lang) {
354
0
  this->ValueObject::SetPreferredDisplayLanguage(lang);
355
0
  if (m_parent)
356
0
    m_parent->SetPreferredDisplayLanguage(lang);
357
0
}
358
359
701
lldb::LanguageType ValueObjectDynamicValue::GetPreferredDisplayLanguage() {
360
701
  if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
361
701
    if (m_parent)
362
701
      return m_parent->GetPreferredDisplayLanguage();
363
0
    return lldb::eLanguageTypeUnknown;
364
701
  } else
365
0
    return m_preferred_display_language;
366
701
}
367
368
0
bool ValueObjectDynamicValue::IsSyntheticChildrenGenerated() {
369
0
  if (m_parent)
370
0
    return m_parent->IsSyntheticChildrenGenerated();
371
0
  return false;
372
0
}
373
374
0
void ValueObjectDynamicValue::SetSyntheticChildrenGenerated(bool b) {
375
0
  if (m_parent)
376
0
    m_parent->SetSyntheticChildrenGenerated(b);
377
0
  this->ValueObject::SetSyntheticChildrenGenerated(b);
378
0
}
379
380
0
bool ValueObjectDynamicValue::GetDeclaration(Declaration &decl) {
381
0
  if (m_parent)
382
0
    return m_parent->GetDeclaration(decl);
383
384
0
  return ValueObject::GetDeclaration(decl);
385
0
}
386
387
0
uint64_t ValueObjectDynamicValue::GetLanguageFlags() {
388
0
  if (m_parent)
389
0
    return m_parent->GetLanguageFlags();
390
0
  return this->ValueObject::GetLanguageFlags();
391
0
}
392
393
0
void ValueObjectDynamicValue::SetLanguageFlags(uint64_t flags) {
394
0
  if (m_parent)
395
0
    m_parent->SetLanguageFlags(flags);
396
0
  else
397
0
    this->ValueObject::SetLanguageFlags(flags);
398
0
}