Coverage Report

Created: 2022-01-18 06:27

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