1 | //===-- SBValue.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/API/SBValue.h" |
10 | #include "lldb/Utility/Instrumentation.h" |
11 | |
12 | #include "lldb/API/SBDeclaration.h" |
13 | #include "lldb/API/SBStream.h" |
14 | #include "lldb/API/SBTypeFilter.h" |
15 | #include "lldb/API/SBTypeFormat.h" |
16 | #include "lldb/API/SBTypeSummary.h" |
17 | #include "lldb/API/SBTypeSynthetic.h" |
18 | |
19 | #include "lldb/Breakpoint/Watchpoint.h" |
20 | #include "lldb/Core/Declaration.h" |
21 | #include "lldb/Core/Module.h" |
22 | #include "lldb/Core/Section.h" |
23 | #include "lldb/Core/Value.h" |
24 | #include "lldb/DataFormatters/DataVisualization.h" |
25 | #include "lldb/DataFormatters/DumpValueObjectOptions.h" |
26 | #include "lldb/Symbol/Block.h" |
27 | #include "lldb/Symbol/ObjectFile.h" |
28 | #include "lldb/Symbol/Type.h" |
29 | #include "lldb/Symbol/Variable.h" |
30 | #include "lldb/Symbol/VariableList.h" |
31 | #include "lldb/Target/ExecutionContext.h" |
32 | #include "lldb/Target/Process.h" |
33 | #include "lldb/Target/StackFrame.h" |
34 | #include "lldb/Target/Target.h" |
35 | #include "lldb/Target/Thread.h" |
36 | #include "lldb/Utility/DataExtractor.h" |
37 | #include "lldb/Utility/Scalar.h" |
38 | #include "lldb/Utility/Stream.h" |
39 | #include "lldb/ValueObject/ValueObject.h" |
40 | #include "lldb/ValueObject/ValueObjectConstResult.h" |
41 | |
42 | #include "lldb/API/SBDebugger.h" |
43 | #include "lldb/API/SBExpressionOptions.h" |
44 | #include "lldb/API/SBFrame.h" |
45 | #include "lldb/API/SBProcess.h" |
46 | #include "lldb/API/SBTarget.h" |
47 | #include "lldb/API/SBThread.h" |
48 | |
49 | #include <memory> |
50 | |
51 | using namespace lldb; |
52 | using namespace lldb_private; |
53 | |
54 | class ValueImpl { |
55 | public: |
56 | ValueImpl() = default; |
57 | |
58 | ValueImpl(lldb::ValueObjectSP in_valobj_sp, |
59 | lldb::DynamicValueType use_dynamic, bool use_synthetic, |
60 | const char *name = nullptr) |
61 | : m_use_dynamic(use_dynamic), m_use_synthetic(use_synthetic), |
62 | m_name(name) { |
63 | if (in_valobj_sp) { |
64 | if ((m_valobj_sp = in_valobj_sp->GetQualifiedRepresentationIfAvailable( |
65 | dynValue: lldb::eNoDynamicValues, synthValue: false))) { |
66 | if (!m_name.IsEmpty()) |
67 | m_valobj_sp->SetName(m_name); |
68 | } |
69 | } |
70 | } |
71 | |
72 | ValueImpl(const ValueImpl &rhs) = default; |
73 | |
74 | ValueImpl &operator=(const ValueImpl &rhs) { |
75 | if (this != &rhs) { |
76 | m_valobj_sp = rhs.m_valobj_sp; |
77 | m_use_dynamic = rhs.m_use_dynamic; |
78 | m_use_synthetic = rhs.m_use_synthetic; |
79 | m_name = rhs.m_name; |
80 | } |
81 | return *this; |
82 | } |
83 | |
84 | bool IsValid() { |
85 | if (m_valobj_sp.get() == nullptr) |
86 | return false; |
87 | else { |
88 | // FIXME: This check is necessary but not sufficient. We for sure don't |
89 | // want to touch SBValues whose owning |
90 | // targets have gone away. This check is a little weak in that it |
91 | // enforces that restriction when you call IsValid, but since IsValid |
92 | // doesn't lock the target, you have no guarantee that the SBValue won't |
93 | // go invalid after you call this... Also, an SBValue could depend on |
94 | // data from one of the modules in the target, and those could go away |
95 | // independently of the target, for instance if a module is unloaded. |
96 | // But right now, neither SBValues nor ValueObjects know which modules |
97 | // they depend on. So I have no good way to make that check without |
98 | // tracking that in all the ValueObject subclasses. |
99 | TargetSP target_sp = m_valobj_sp->GetTargetSP(); |
100 | return target_sp && target_sp->IsValid(); |
101 | } |
102 | } |
103 | |
104 | lldb::ValueObjectSP GetRootSP() { return m_valobj_sp; } |
105 | |
106 | lldb::ValueObjectSP GetSP(Process::StopLocker &stop_locker, |
107 | std::unique_lock<std::recursive_mutex> &lock, |
108 | Status &error) { |
109 | if (!m_valobj_sp) { |
110 | error = Status::FromErrorString(str: "invalid value object"); |
111 | return m_valobj_sp; |
112 | } |
113 | |
114 | lldb::ValueObjectSP value_sp = m_valobj_sp; |
115 | |
116 | Target *target = value_sp->GetTargetSP().get(); |
117 | // If this ValueObject holds an error, then it is valuable for that. |
118 | if (value_sp->GetError().Fail()) |
119 | return value_sp; |
120 | |
121 | if (!target) |
122 | return ValueObjectSP(); |
123 | |
124 | lock = std::unique_lock<std::recursive_mutex>(target->GetAPIMutex()); |
125 | |
126 | ProcessSP process_sp(value_sp->GetProcessSP()); |
127 | if (process_sp && !stop_locker.TryLock(lock: &process_sp->GetRunLock())) { |
128 | // We don't allow people to play around with ValueObject if the process |
129 | // is running. If you want to look at values, pause the process, then |
130 | // look. |
131 | error = Status::FromErrorString(str: "process must be stopped."); |
132 | return ValueObjectSP(); |
133 | } |
134 | |
135 | if (m_use_dynamic != eNoDynamicValues) { |
136 | ValueObjectSP dynamic_sp = value_sp->GetDynamicValue(valueType: m_use_dynamic); |
137 | if (dynamic_sp) |
138 | value_sp = dynamic_sp; |
139 | } |
140 | |
141 | if (m_use_synthetic) { |
142 | ValueObjectSP synthetic_sp = value_sp->GetSyntheticValue(); |
143 | if (synthetic_sp) |
144 | value_sp = synthetic_sp; |
145 | } |
146 | |
147 | if (!value_sp) |
148 | error = Status::FromErrorString(str: "invalid value object"); |
149 | if (!m_name.IsEmpty()) |
150 | value_sp->SetName(m_name); |
151 | |
152 | return value_sp; |
153 | } |
154 | |
155 | void SetUseDynamic(lldb::DynamicValueType use_dynamic) { |
156 | m_use_dynamic = use_dynamic; |
157 | } |
158 | |
159 | void SetUseSynthetic(bool use_synthetic) { m_use_synthetic = use_synthetic; } |
160 | |
161 | lldb::DynamicValueType GetUseDynamic() { return m_use_dynamic; } |
162 | |
163 | bool GetUseSynthetic() { return m_use_synthetic; } |
164 | |
165 | // All the derived values that we would make from the m_valobj_sp will share |
166 | // the ExecutionContext with m_valobj_sp, so we don't need to do the |
167 | // calculations in GetSP to return the Target, Process, Thread or Frame. It |
168 | // is convenient to provide simple accessors for these, which I do here. |
169 | TargetSP GetTargetSP() { |
170 | if (m_valobj_sp) |
171 | return m_valobj_sp->GetTargetSP(); |
172 | else |
173 | return TargetSP(); |
174 | } |
175 | |
176 | ProcessSP GetProcessSP() { |
177 | if (m_valobj_sp) |
178 | return m_valobj_sp->GetProcessSP(); |
179 | else |
180 | return ProcessSP(); |
181 | } |
182 | |
183 | ThreadSP GetThreadSP() { |
184 | if (m_valobj_sp) |
185 | return m_valobj_sp->GetThreadSP(); |
186 | else |
187 | return ThreadSP(); |
188 | } |
189 | |
190 | StackFrameSP GetFrameSP() { |
191 | if (m_valobj_sp) |
192 | return m_valobj_sp->GetFrameSP(); |
193 | else |
194 | return StackFrameSP(); |
195 | } |
196 | |
197 | private: |
198 | lldb::ValueObjectSP m_valobj_sp; |
199 | lldb::DynamicValueType m_use_dynamic; |
200 | bool m_use_synthetic; |
201 | ConstString m_name; |
202 | }; |
203 | |
204 | class ValueLocker { |
205 | public: |
206 | ValueLocker() = default; |
207 | |
208 | ValueObjectSP GetLockedSP(ValueImpl &in_value) { |
209 | return in_value.GetSP(stop_locker&: m_stop_locker, lock&: m_lock, error&: m_lock_error); |
210 | } |
211 | |
212 | Status &GetError() { return m_lock_error; } |
213 | |
214 | private: |
215 | Process::StopLocker m_stop_locker; |
216 | std::unique_lock<std::recursive_mutex> m_lock; |
217 | Status m_lock_error; |
218 | }; |
219 | |
220 | SBValue::SBValue() { LLDB_INSTRUMENT_VA(this); } |
221 | |
222 | SBValue::SBValue(const lldb::ValueObjectSP &value_sp) { |
223 | LLDB_INSTRUMENT_VA(this, value_sp); |
224 | |
225 | SetSP(value_sp); |
226 | } |
227 | |
228 | SBValue::SBValue(const SBValue &rhs) { |
229 | LLDB_INSTRUMENT_VA(this, rhs); |
230 | |
231 | SetSP(rhs.m_opaque_sp); |
232 | } |
233 | |
234 | SBValue &SBValue::operator=(const SBValue &rhs) { |
235 | LLDB_INSTRUMENT_VA(this, rhs); |
236 | |
237 | if (this != &rhs) { |
238 | SetSP(rhs.m_opaque_sp); |
239 | } |
240 | return *this; |
241 | } |
242 | |
243 | SBValue::~SBValue() = default; |
244 | |
245 | bool SBValue::IsValid() { |
246 | LLDB_INSTRUMENT_VA(this); |
247 | return this->operator bool(); |
248 | } |
249 | SBValue::operator bool() const { |
250 | LLDB_INSTRUMENT_VA(this); |
251 | |
252 | // If this function ever changes to anything that does more than just check |
253 | // if the opaque shared pointer is non NULL, then we need to update all "if |
254 | // (m_opaque_sp)" code in this file. |
255 | return m_opaque_sp.get() != nullptr && m_opaque_sp->IsValid() && |
256 | m_opaque_sp->GetRootSP().get() != nullptr; |
257 | } |
258 | |
259 | void SBValue::Clear() { |
260 | LLDB_INSTRUMENT_VA(this); |
261 | |
262 | m_opaque_sp.reset(); |
263 | } |
264 | |
265 | SBError SBValue::GetError() { |
266 | LLDB_INSTRUMENT_VA(this); |
267 | |
268 | SBError sb_error; |
269 | |
270 | ValueLocker locker; |
271 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
272 | if (value_sp) |
273 | sb_error.SetError(value_sp->GetError().Clone()); |
274 | else |
275 | sb_error = Status::FromErrorStringWithFormat(format: "error: %s", |
276 | locker.GetError().AsCString()); |
277 | |
278 | return sb_error; |
279 | } |
280 | |
281 | user_id_t SBValue::GetID() { |
282 | LLDB_INSTRUMENT_VA(this); |
283 | |
284 | ValueLocker locker; |
285 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
286 | if (value_sp) |
287 | return value_sp->GetID(); |
288 | return LLDB_INVALID_UID; |
289 | } |
290 | |
291 | const char *SBValue::GetName() { |
292 | LLDB_INSTRUMENT_VA(this); |
293 | |
294 | ValueLocker locker; |
295 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
296 | if (!value_sp) |
297 | return nullptr; |
298 | |
299 | return value_sp->GetName().GetCString(); |
300 | } |
301 | |
302 | const char *SBValue::GetTypeName() { |
303 | LLDB_INSTRUMENT_VA(this); |
304 | |
305 | ValueLocker locker; |
306 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
307 | if (!value_sp) |
308 | return nullptr; |
309 | |
310 | return value_sp->GetQualifiedTypeName().GetCString(); |
311 | } |
312 | |
313 | const char *SBValue::GetDisplayTypeName() { |
314 | LLDB_INSTRUMENT_VA(this); |
315 | |
316 | ValueLocker locker; |
317 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
318 | if (!value_sp) |
319 | return nullptr; |
320 | |
321 | return value_sp->GetDisplayTypeName().GetCString(); |
322 | } |
323 | |
324 | size_t SBValue::GetByteSize() { |
325 | LLDB_INSTRUMENT_VA(this); |
326 | |
327 | size_t result = 0; |
328 | |
329 | ValueLocker locker; |
330 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
331 | if (value_sp) { |
332 | result = llvm::expectedToOptional(E: value_sp->GetByteSize()).value_or(u: 0); |
333 | } |
334 | |
335 | return result; |
336 | } |
337 | |
338 | bool SBValue::IsInScope() { |
339 | LLDB_INSTRUMENT_VA(this); |
340 | |
341 | bool result = false; |
342 | |
343 | ValueLocker locker; |
344 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
345 | if (value_sp) { |
346 | result = value_sp->IsInScope(); |
347 | } |
348 | |
349 | return result; |
350 | } |
351 | |
352 | const char *SBValue::GetValue() { |
353 | LLDB_INSTRUMENT_VA(this); |
354 | |
355 | ValueLocker locker; |
356 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
357 | if (!value_sp) |
358 | return nullptr; |
359 | return ConstString(value_sp->GetValueAsCString()).GetCString(); |
360 | } |
361 | |
362 | ValueType SBValue::GetValueType() { |
363 | LLDB_INSTRUMENT_VA(this); |
364 | |
365 | ValueType result = eValueTypeInvalid; |
366 | ValueLocker locker; |
367 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
368 | if (value_sp) |
369 | result = value_sp->GetValueType(); |
370 | |
371 | return result; |
372 | } |
373 | |
374 | const char *SBValue::GetObjectDescription() { |
375 | LLDB_INSTRUMENT_VA(this); |
376 | |
377 | ValueLocker locker; |
378 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
379 | if (!value_sp) |
380 | return nullptr; |
381 | |
382 | llvm::Expected<std::string> str = value_sp->GetObjectDescription(); |
383 | if (!str) { |
384 | llvm::consumeError(Err: str.takeError()); |
385 | return nullptr; |
386 | } |
387 | return ConstString(*str).AsCString(); |
388 | } |
389 | |
390 | SBType SBValue::GetType() { |
391 | LLDB_INSTRUMENT_VA(this); |
392 | |
393 | SBType sb_type; |
394 | ValueLocker locker; |
395 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
396 | TypeImplSP type_sp; |
397 | if (value_sp) { |
398 | type_sp = std::make_shared<TypeImpl>(args: value_sp->GetTypeImpl()); |
399 | sb_type.SetSP(type_sp); |
400 | } |
401 | |
402 | return sb_type; |
403 | } |
404 | |
405 | bool SBValue::GetValueDidChange() { |
406 | LLDB_INSTRUMENT_VA(this); |
407 | |
408 | bool result = false; |
409 | ValueLocker locker; |
410 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
411 | if (value_sp) { |
412 | if (value_sp->UpdateValueIfNeeded(update_format: false)) |
413 | result = value_sp->GetValueDidChange(); |
414 | } |
415 | |
416 | return result; |
417 | } |
418 | |
419 | const char *SBValue::GetSummary() { |
420 | LLDB_INSTRUMENT_VA(this); |
421 | |
422 | ValueLocker locker; |
423 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
424 | if (!value_sp) |
425 | return nullptr; |
426 | |
427 | return ConstString(value_sp->GetSummaryAsCString()).GetCString(); |
428 | } |
429 | |
430 | const char *SBValue::GetSummary(lldb::SBStream &stream, |
431 | lldb::SBTypeSummaryOptions &options) { |
432 | LLDB_INSTRUMENT_VA(this, stream, options); |
433 | |
434 | ValueLocker locker; |
435 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
436 | if (value_sp) { |
437 | std::string buffer; |
438 | if (value_sp->GetSummaryAsCString(destination&: buffer, options: options.ref()) && !buffer.empty()) |
439 | stream.Printf(format: "%s", buffer.c_str()); |
440 | } |
441 | return ConstString(stream.GetData()).GetCString(); |
442 | } |
443 | |
444 | const char *SBValue::GetLocation() { |
445 | LLDB_INSTRUMENT_VA(this); |
446 | |
447 | ValueLocker locker; |
448 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
449 | if (!value_sp) |
450 | return nullptr; |
451 | |
452 | return ConstString(value_sp->GetLocationAsCString()).GetCString(); |
453 | } |
454 | |
455 | // Deprecated - use the one that takes an lldb::SBError |
456 | bool SBValue::SetValueFromCString(const char *value_str) { |
457 | LLDB_INSTRUMENT_VA(this, value_str); |
458 | |
459 | lldb::SBError dummy; |
460 | return SetValueFromCString(value_str, error&: dummy); |
461 | } |
462 | |
463 | bool SBValue::SetValueFromCString(const char *value_str, lldb::SBError &error) { |
464 | LLDB_INSTRUMENT_VA(this, value_str, error); |
465 | |
466 | bool success = false; |
467 | ValueLocker locker; |
468 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
469 | if (value_sp) { |
470 | success = value_sp->SetValueFromCString(value_str, error&: error.ref()); |
471 | } else |
472 | error = Status::FromErrorStringWithFormat(format: "Could not get value: %s", |
473 | locker.GetError().AsCString()); |
474 | |
475 | return success; |
476 | } |
477 | |
478 | lldb::SBTypeFormat SBValue::GetTypeFormat() { |
479 | LLDB_INSTRUMENT_VA(this); |
480 | |
481 | lldb::SBTypeFormat format; |
482 | ValueLocker locker; |
483 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
484 | if (value_sp) { |
485 | if (value_sp->UpdateValueIfNeeded(update_format: true)) { |
486 | lldb::TypeFormatImplSP format_sp = value_sp->GetValueFormat(); |
487 | if (format_sp) |
488 | format.SetSP(format_sp); |
489 | } |
490 | } |
491 | return format; |
492 | } |
493 | |
494 | lldb::SBTypeSummary SBValue::GetTypeSummary() { |
495 | LLDB_INSTRUMENT_VA(this); |
496 | |
497 | lldb::SBTypeSummary summary; |
498 | ValueLocker locker; |
499 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
500 | if (value_sp) { |
501 | if (value_sp->UpdateValueIfNeeded(update_format: true)) { |
502 | lldb::TypeSummaryImplSP summary_sp = value_sp->GetSummaryFormat(); |
503 | if (summary_sp) |
504 | summary.SetSP(summary_sp); |
505 | } |
506 | } |
507 | return summary; |
508 | } |
509 | |
510 | lldb::SBTypeFilter SBValue::GetTypeFilter() { |
511 | LLDB_INSTRUMENT_VA(this); |
512 | |
513 | lldb::SBTypeFilter filter; |
514 | ValueLocker locker; |
515 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
516 | if (value_sp) { |
517 | if (value_sp->UpdateValueIfNeeded(update_format: true)) { |
518 | lldb::SyntheticChildrenSP synthetic_sp = value_sp->GetSyntheticChildren(); |
519 | |
520 | if (synthetic_sp && !synthetic_sp->IsScripted()) { |
521 | TypeFilterImplSP filter_sp = |
522 | std::static_pointer_cast<TypeFilterImpl>(r: synthetic_sp); |
523 | filter.SetSP(filter_sp); |
524 | } |
525 | } |
526 | } |
527 | return filter; |
528 | } |
529 | |
530 | lldb::SBTypeSynthetic SBValue::GetTypeSynthetic() { |
531 | LLDB_INSTRUMENT_VA(this); |
532 | |
533 | lldb::SBTypeSynthetic synthetic; |
534 | ValueLocker locker; |
535 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
536 | if (value_sp) { |
537 | if (value_sp->UpdateValueIfNeeded(update_format: true)) { |
538 | lldb::SyntheticChildrenSP children_sp = value_sp->GetSyntheticChildren(); |
539 | |
540 | if (children_sp && children_sp->IsScripted()) { |
541 | ScriptedSyntheticChildrenSP synth_sp = |
542 | std::static_pointer_cast<ScriptedSyntheticChildren>(r: children_sp); |
543 | synthetic.SetSP(synth_sp); |
544 | } |
545 | } |
546 | } |
547 | return synthetic; |
548 | } |
549 | |
550 | lldb::SBValue SBValue::CreateChildAtOffset(const char *name, uint32_t offset, |
551 | SBType type) { |
552 | LLDB_INSTRUMENT_VA(this, name, offset, type); |
553 | |
554 | lldb::SBValue sb_value; |
555 | ValueLocker locker; |
556 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
557 | lldb::ValueObjectSP new_value_sp; |
558 | if (value_sp) { |
559 | TypeImplSP type_sp(type.GetSP()); |
560 | if (type.IsValid()) { |
561 | sb_value.SetSP(sp: value_sp->GetSyntheticChildAtOffset( |
562 | offset, type: type_sp->GetCompilerType(prefer_dynamic: false), can_create: true), |
563 | use_dynamic: GetPreferDynamicValue(), use_synthetic: GetPreferSyntheticValue(), name); |
564 | } |
565 | } |
566 | return sb_value; |
567 | } |
568 | |
569 | lldb::SBValue SBValue::Cast(SBType type) { |
570 | LLDB_INSTRUMENT_VA(this, type); |
571 | |
572 | lldb::SBValue sb_value; |
573 | ValueLocker locker; |
574 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
575 | TypeImplSP type_sp(type.GetSP()); |
576 | if (value_sp && type_sp) |
577 | sb_value.SetSP(sp: value_sp->Cast(compiler_type: type_sp->GetCompilerType(prefer_dynamic: false)), |
578 | use_dynamic: GetPreferDynamicValue(), use_synthetic: GetPreferSyntheticValue()); |
579 | return sb_value; |
580 | } |
581 | |
582 | lldb::SBValue SBValue::CreateValueFromExpression(const char *name, |
583 | const char *expression) { |
584 | LLDB_INSTRUMENT_VA(this, name, expression); |
585 | |
586 | SBExpressionOptions options; |
587 | options.ref().SetKeepInMemory(true); |
588 | return CreateValueFromExpression(name, expression, options); |
589 | } |
590 | |
591 | lldb::SBValue SBValue::CreateValueFromExpression(const char *name, |
592 | const char *expression, |
593 | SBExpressionOptions &options) { |
594 | LLDB_INSTRUMENT_VA(this, name, expression, options); |
595 | |
596 | lldb::SBValue sb_value; |
597 | ValueLocker locker; |
598 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
599 | lldb::ValueObjectSP new_value_sp; |
600 | if (value_sp) { |
601 | ExecutionContext exe_ctx(value_sp->GetExecutionContextRef()); |
602 | new_value_sp = ValueObject::CreateValueObjectFromExpression( |
603 | name, expression, exe_ctx, options: options.ref()); |
604 | if (new_value_sp) |
605 | new_value_sp->SetName(ConstString(name)); |
606 | } |
607 | sb_value.SetSP(new_value_sp); |
608 | return sb_value; |
609 | } |
610 | |
611 | lldb::SBValue SBValue::CreateValueFromAddress(const char *name, |
612 | lldb::addr_t address, |
613 | SBType sb_type) { |
614 | LLDB_INSTRUMENT_VA(this, name, address, sb_type); |
615 | |
616 | lldb::SBValue sb_value; |
617 | ValueLocker locker; |
618 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
619 | lldb::ValueObjectSP new_value_sp; |
620 | lldb::TypeImplSP type_impl_sp(sb_type.GetSP()); |
621 | if (value_sp && type_impl_sp) { |
622 | CompilerType ast_type(type_impl_sp->GetCompilerType(prefer_dynamic: true)); |
623 | ExecutionContext exe_ctx(value_sp->GetExecutionContextRef()); |
624 | new_value_sp = ValueObject::CreateValueObjectFromAddress(name, address, |
625 | exe_ctx, type: ast_type); |
626 | } |
627 | sb_value.SetSP(new_value_sp); |
628 | return sb_value; |
629 | } |
630 | |
631 | lldb::SBValue SBValue::CreateValueFromData(const char *name, SBData data, |
632 | SBType sb_type) { |
633 | LLDB_INSTRUMENT_VA(this, name, data, sb_type); |
634 | |
635 | lldb::SBValue sb_value; |
636 | lldb::ValueObjectSP new_value_sp; |
637 | ValueLocker locker; |
638 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
639 | lldb::TypeImplSP type_impl_sp(sb_type.GetSP()); |
640 | if (value_sp && type_impl_sp) { |
641 | ExecutionContext exe_ctx(value_sp->GetExecutionContextRef()); |
642 | new_value_sp = ValueObject::CreateValueObjectFromData( |
643 | name, data: **data, exe_ctx, type: type_impl_sp->GetCompilerType(prefer_dynamic: true)); |
644 | new_value_sp->SetAddressTypeOfChildren(eAddressTypeLoad); |
645 | } |
646 | sb_value.SetSP(new_value_sp); |
647 | return sb_value; |
648 | } |
649 | |
650 | lldb::SBValue SBValue::CreateBoolValue(const char *name, bool value) { |
651 | LLDB_INSTRUMENT_VA(this, name); |
652 | |
653 | lldb::SBValue sb_value; |
654 | lldb::ValueObjectSP new_value_sp; |
655 | ValueLocker locker; |
656 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
657 | lldb::TargetSP target_sp = m_opaque_sp->GetTargetSP(); |
658 | if (value_sp && target_sp) { |
659 | new_value_sp = |
660 | ValueObject::CreateValueObjectFromBool(target: target_sp, value, name); |
661 | } |
662 | sb_value.SetSP(new_value_sp); |
663 | return sb_value; |
664 | } |
665 | |
666 | SBValue SBValue::GetChildAtIndex(uint32_t idx) { |
667 | LLDB_INSTRUMENT_VA(this, idx); |
668 | |
669 | lldb::DynamicValueType use_dynamic = eNoDynamicValues; |
670 | TargetSP target_sp; |
671 | if (m_opaque_sp) |
672 | target_sp = m_opaque_sp->GetTargetSP(); |
673 | |
674 | if (target_sp) |
675 | use_dynamic = target_sp->GetPreferDynamicValue(); |
676 | |
677 | return GetChildAtIndex(idx, use_dynamic, /*treat_as_array=*/false); |
678 | } |
679 | |
680 | SBValue SBValue::GetChildAtIndex(uint32_t idx, |
681 | lldb::DynamicValueType use_dynamic, |
682 | bool treat_as_array) { |
683 | LLDB_INSTRUMENT_VA(this, idx, use_dynamic, treat_as_array); |
684 | ValueLocker locker; |
685 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
686 | |
687 | lldb::ValueObjectSP child_sp; |
688 | if (value_sp) { |
689 | const bool can_create = true; |
690 | if (treat_as_array && |
691 | (value_sp->IsPointerType() || value_sp->IsArrayType())) |
692 | child_sp = value_sp->GetSyntheticArrayMember(index: idx, can_create); |
693 | else |
694 | child_sp = value_sp->GetChildAtIndex(idx); |
695 | } |
696 | |
697 | SBValue sb_value; |
698 | sb_value.SetSP(sp: child_sp, use_dynamic, use_synthetic: GetPreferSyntheticValue()); |
699 | |
700 | return sb_value; |
701 | } |
702 | |
703 | uint32_t SBValue::GetIndexOfChildWithName(const char *name) { |
704 | LLDB_INSTRUMENT_VA(this, name); |
705 | |
706 | ValueLocker locker; |
707 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
708 | if (value_sp) { |
709 | if (auto idx_or_err = value_sp->GetIndexOfChildWithName(name)) |
710 | return *idx_or_err; |
711 | else |
712 | llvm::consumeError(Err: idx_or_err.takeError()); |
713 | } |
714 | return UINT32_MAX; |
715 | } |
716 | |
717 | SBValue SBValue::GetChildMemberWithName(const char *name) { |
718 | LLDB_INSTRUMENT_VA(this, name); |
719 | |
720 | lldb::DynamicValueType use_dynamic_value = eNoDynamicValues; |
721 | TargetSP target_sp; |
722 | if (m_opaque_sp) |
723 | target_sp = m_opaque_sp->GetTargetSP(); |
724 | |
725 | if (target_sp) |
726 | use_dynamic_value = target_sp->GetPreferDynamicValue(); |
727 | return GetChildMemberWithName(name, use_dynamic: use_dynamic_value); |
728 | } |
729 | |
730 | SBValue |
731 | SBValue::GetChildMemberWithName(const char *name, |
732 | lldb::DynamicValueType use_dynamic_value) { |
733 | LLDB_INSTRUMENT_VA(this, name, use_dynamic_value); |
734 | |
735 | lldb::ValueObjectSP child_sp; |
736 | |
737 | ValueLocker locker; |
738 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
739 | if (value_sp) { |
740 | child_sp = value_sp->GetChildMemberWithName(name); |
741 | } |
742 | |
743 | SBValue sb_value; |
744 | sb_value.SetSP(sp: child_sp, use_dynamic: use_dynamic_value, use_synthetic: GetPreferSyntheticValue()); |
745 | |
746 | return sb_value; |
747 | } |
748 | |
749 | lldb::SBValue SBValue::GetDynamicValue(lldb::DynamicValueType use_dynamic) { |
750 | LLDB_INSTRUMENT_VA(this, use_dynamic); |
751 | |
752 | SBValue value_sb; |
753 | if (IsValid()) { |
754 | ValueImplSP proxy_sp(new ValueImpl(m_opaque_sp->GetRootSP(), use_dynamic, |
755 | m_opaque_sp->GetUseSynthetic())); |
756 | value_sb.SetSP(proxy_sp); |
757 | } |
758 | return value_sb; |
759 | } |
760 | |
761 | lldb::SBValue SBValue::GetStaticValue() { |
762 | LLDB_INSTRUMENT_VA(this); |
763 | |
764 | SBValue value_sb; |
765 | if (IsValid()) { |
766 | ValueImplSP proxy_sp(new ValueImpl(m_opaque_sp->GetRootSP(), |
767 | eNoDynamicValues, |
768 | m_opaque_sp->GetUseSynthetic())); |
769 | value_sb.SetSP(proxy_sp); |
770 | } |
771 | return value_sb; |
772 | } |
773 | |
774 | lldb::SBValue SBValue::GetNonSyntheticValue() { |
775 | LLDB_INSTRUMENT_VA(this); |
776 | |
777 | SBValue value_sb; |
778 | if (IsValid()) { |
779 | ValueImplSP proxy_sp(new ValueImpl(m_opaque_sp->GetRootSP(), |
780 | m_opaque_sp->GetUseDynamic(), false)); |
781 | value_sb.SetSP(proxy_sp); |
782 | } |
783 | return value_sb; |
784 | } |
785 | |
786 | lldb::SBValue SBValue::GetSyntheticValue() { |
787 | LLDB_INSTRUMENT_VA(this); |
788 | |
789 | SBValue value_sb; |
790 | if (IsValid()) { |
791 | ValueImplSP proxy_sp(new ValueImpl(m_opaque_sp->GetRootSP(), |
792 | m_opaque_sp->GetUseDynamic(), true)); |
793 | value_sb.SetSP(proxy_sp); |
794 | if (!value_sb.IsSynthetic()) { |
795 | return {}; |
796 | } |
797 | } |
798 | return value_sb; |
799 | } |
800 | |
801 | lldb::DynamicValueType SBValue::GetPreferDynamicValue() { |
802 | LLDB_INSTRUMENT_VA(this); |
803 | |
804 | if (!IsValid()) |
805 | return eNoDynamicValues; |
806 | return m_opaque_sp->GetUseDynamic(); |
807 | } |
808 | |
809 | void SBValue::SetPreferDynamicValue(lldb::DynamicValueType use_dynamic) { |
810 | LLDB_INSTRUMENT_VA(this, use_dynamic); |
811 | |
812 | if (IsValid()) |
813 | return m_opaque_sp->SetUseDynamic(use_dynamic); |
814 | } |
815 | |
816 | bool SBValue::GetPreferSyntheticValue() { |
817 | LLDB_INSTRUMENT_VA(this); |
818 | |
819 | if (!IsValid()) |
820 | return false; |
821 | return m_opaque_sp->GetUseSynthetic(); |
822 | } |
823 | |
824 | void SBValue::SetPreferSyntheticValue(bool use_synthetic) { |
825 | LLDB_INSTRUMENT_VA(this, use_synthetic); |
826 | |
827 | if (IsValid()) |
828 | return m_opaque_sp->SetUseSynthetic(use_synthetic); |
829 | } |
830 | |
831 | bool SBValue::IsDynamic() { |
832 | LLDB_INSTRUMENT_VA(this); |
833 | |
834 | ValueLocker locker; |
835 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
836 | if (value_sp) |
837 | return value_sp->IsDynamic(); |
838 | return false; |
839 | } |
840 | |
841 | bool SBValue::IsSynthetic() { |
842 | LLDB_INSTRUMENT_VA(this); |
843 | |
844 | ValueLocker locker; |
845 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
846 | if (value_sp) |
847 | return value_sp->IsSynthetic(); |
848 | return false; |
849 | } |
850 | |
851 | bool SBValue::IsSyntheticChildrenGenerated() { |
852 | LLDB_INSTRUMENT_VA(this); |
853 | |
854 | ValueLocker locker; |
855 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
856 | if (value_sp) |
857 | return value_sp->IsSyntheticChildrenGenerated(); |
858 | return false; |
859 | } |
860 | |
861 | void SBValue::SetSyntheticChildrenGenerated(bool is) { |
862 | LLDB_INSTRUMENT_VA(this, is); |
863 | |
864 | ValueLocker locker; |
865 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
866 | if (value_sp) |
867 | return value_sp->SetSyntheticChildrenGenerated(is); |
868 | } |
869 | |
870 | lldb::SBValue SBValue::GetValueForExpressionPath(const char *expr_path) { |
871 | LLDB_INSTRUMENT_VA(this, expr_path); |
872 | |
873 | lldb::ValueObjectSP child_sp; |
874 | ValueLocker locker; |
875 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
876 | if (value_sp) { |
877 | // using default values for all the fancy options, just do it if you can |
878 | child_sp = value_sp->GetValueForExpressionPath(expression: expr_path); |
879 | } |
880 | |
881 | SBValue sb_value; |
882 | sb_value.SetSP(sp: child_sp, use_dynamic: GetPreferDynamicValue(), use_synthetic: GetPreferSyntheticValue()); |
883 | |
884 | return sb_value; |
885 | } |
886 | |
887 | int64_t SBValue::GetValueAsSigned(SBError &error, int64_t fail_value) { |
888 | LLDB_INSTRUMENT_VA(this, error, fail_value); |
889 | |
890 | error.Clear(); |
891 | ValueLocker locker; |
892 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
893 | if (value_sp) { |
894 | bool success = true; |
895 | uint64_t ret_val = fail_value; |
896 | ret_val = value_sp->GetValueAsSigned(fail_value, success: &success); |
897 | if (!success) |
898 | error = Status::FromErrorString(str: "could not resolve value"); |
899 | return ret_val; |
900 | } else |
901 | error = Status::FromErrorStringWithFormat(format: "could not get SBValue: %s", |
902 | locker.GetError().AsCString()); |
903 | |
904 | return fail_value; |
905 | } |
906 | |
907 | uint64_t SBValue::GetValueAsUnsigned(SBError &error, uint64_t fail_value) { |
908 | LLDB_INSTRUMENT_VA(this, error, fail_value); |
909 | |
910 | error.Clear(); |
911 | ValueLocker locker; |
912 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
913 | if (value_sp) { |
914 | bool success = true; |
915 | uint64_t ret_val = fail_value; |
916 | ret_val = value_sp->GetValueAsUnsigned(fail_value, success: &success); |
917 | if (!success) |
918 | error = Status::FromErrorString(str: "could not resolve value"); |
919 | return ret_val; |
920 | } else |
921 | error = Status::FromErrorStringWithFormat(format: "could not get SBValue: %s", |
922 | locker.GetError().AsCString()); |
923 | |
924 | return fail_value; |
925 | } |
926 | |
927 | int64_t SBValue::GetValueAsSigned(int64_t fail_value) { |
928 | LLDB_INSTRUMENT_VA(this, fail_value); |
929 | |
930 | ValueLocker locker; |
931 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
932 | if (value_sp) { |
933 | return value_sp->GetValueAsSigned(fail_value); |
934 | } |
935 | return fail_value; |
936 | } |
937 | |
938 | uint64_t SBValue::GetValueAsUnsigned(uint64_t fail_value) { |
939 | LLDB_INSTRUMENT_VA(this, fail_value); |
940 | |
941 | ValueLocker locker; |
942 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
943 | if (value_sp) { |
944 | return value_sp->GetValueAsUnsigned(fail_value); |
945 | } |
946 | return fail_value; |
947 | } |
948 | |
949 | lldb::addr_t SBValue::GetValueAsAddress() { |
950 | addr_t fail_value = LLDB_INVALID_ADDRESS; |
951 | ValueLocker locker; |
952 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
953 | if (value_sp) { |
954 | bool success = true; |
955 | uint64_t ret_val = fail_value; |
956 | ret_val = value_sp->GetValueAsUnsigned(fail_value, success: &success); |
957 | if (!success) |
958 | return fail_value; |
959 | ProcessSP process_sp = m_opaque_sp->GetProcessSP(); |
960 | if (!process_sp) |
961 | return ret_val; |
962 | return process_sp->FixDataAddress(pc: ret_val); |
963 | } |
964 | |
965 | return fail_value; |
966 | } |
967 | |
968 | bool SBValue::MightHaveChildren() { |
969 | LLDB_INSTRUMENT_VA(this); |
970 | |
971 | bool has_children = false; |
972 | ValueLocker locker; |
973 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
974 | if (value_sp) |
975 | has_children = value_sp->MightHaveChildren(); |
976 | |
977 | return has_children; |
978 | } |
979 | |
980 | bool SBValue::IsRuntimeSupportValue() { |
981 | LLDB_INSTRUMENT_VA(this); |
982 | |
983 | bool is_support = false; |
984 | ValueLocker locker; |
985 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
986 | if (value_sp) |
987 | is_support = value_sp->IsRuntimeSupportValue(); |
988 | |
989 | return is_support; |
990 | } |
991 | |
992 | uint32_t SBValue::GetNumChildren() { |
993 | LLDB_INSTRUMENT_VA(this); |
994 | |
995 | return GetNumChildren(UINT32_MAX); |
996 | } |
997 | |
998 | uint32_t SBValue::GetNumChildren(uint32_t max) { |
999 | LLDB_INSTRUMENT_VA(this, max); |
1000 | |
1001 | uint32_t num_children = 0; |
1002 | |
1003 | ValueLocker locker; |
1004 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
1005 | if (value_sp) |
1006 | num_children = value_sp->GetNumChildrenIgnoringErrors(max); |
1007 | |
1008 | return num_children; |
1009 | } |
1010 | |
1011 | SBValue SBValue::Dereference() { |
1012 | LLDB_INSTRUMENT_VA(this); |
1013 | |
1014 | SBValue sb_value; |
1015 | ValueLocker locker; |
1016 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
1017 | if (value_sp) { |
1018 | Status error; |
1019 | sb_value = value_sp->Dereference(error); |
1020 | } |
1021 | |
1022 | return sb_value; |
1023 | } |
1024 | |
1025 | // Deprecated - please use GetType().IsPointerType() instead. |
1026 | bool SBValue::TypeIsPointerType() { |
1027 | LLDB_INSTRUMENT_VA(this); |
1028 | |
1029 | return GetType().IsPointerType(); |
1030 | } |
1031 | |
1032 | void *SBValue::GetOpaqueType() { |
1033 | LLDB_INSTRUMENT_VA(this); |
1034 | |
1035 | ValueLocker locker; |
1036 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
1037 | if (value_sp) |
1038 | return value_sp->GetCompilerType().GetOpaqueQualType(); |
1039 | return nullptr; |
1040 | } |
1041 | |
1042 | lldb::SBTarget SBValue::GetTarget() { |
1043 | LLDB_INSTRUMENT_VA(this); |
1044 | |
1045 | SBTarget sb_target; |
1046 | TargetSP target_sp; |
1047 | if (m_opaque_sp) { |
1048 | target_sp = m_opaque_sp->GetTargetSP(); |
1049 | sb_target.SetSP(target_sp); |
1050 | } |
1051 | |
1052 | return sb_target; |
1053 | } |
1054 | |
1055 | lldb::SBProcess SBValue::GetProcess() { |
1056 | LLDB_INSTRUMENT_VA(this); |
1057 | |
1058 | SBProcess sb_process; |
1059 | ProcessSP process_sp; |
1060 | if (m_opaque_sp) { |
1061 | process_sp = m_opaque_sp->GetProcessSP(); |
1062 | sb_process.SetSP(process_sp); |
1063 | } |
1064 | |
1065 | return sb_process; |
1066 | } |
1067 | |
1068 | lldb::SBThread SBValue::GetThread() { |
1069 | LLDB_INSTRUMENT_VA(this); |
1070 | |
1071 | SBThread sb_thread; |
1072 | ThreadSP thread_sp; |
1073 | if (m_opaque_sp) { |
1074 | thread_sp = m_opaque_sp->GetThreadSP(); |
1075 | sb_thread.SetThread(thread_sp); |
1076 | } |
1077 | |
1078 | return sb_thread; |
1079 | } |
1080 | |
1081 | lldb::SBFrame SBValue::GetFrame() { |
1082 | LLDB_INSTRUMENT_VA(this); |
1083 | |
1084 | SBFrame sb_frame; |
1085 | StackFrameSP frame_sp; |
1086 | if (m_opaque_sp) { |
1087 | frame_sp = m_opaque_sp->GetFrameSP(); |
1088 | sb_frame.SetFrameSP(frame_sp); |
1089 | } |
1090 | |
1091 | return sb_frame; |
1092 | } |
1093 | |
1094 | lldb::ValueObjectSP SBValue::GetSP(ValueLocker &locker) const { |
1095 | // IsValid means that the SBValue has a value in it. But that's not the |
1096 | // only time that ValueObjects are useful. We also want to return the value |
1097 | // if there's an error state in it. |
1098 | if (!m_opaque_sp || (!m_opaque_sp->IsValid() |
1099 | && (m_opaque_sp->GetRootSP() |
1100 | && !m_opaque_sp->GetRootSP()->GetError().Fail()))) { |
1101 | locker.GetError() = Status::FromErrorString(str: "No value"); |
1102 | return ValueObjectSP(); |
1103 | } |
1104 | return locker.GetLockedSP(in_value&: *m_opaque_sp.get()); |
1105 | } |
1106 | |
1107 | lldb::ValueObjectSP SBValue::GetSP() const { |
1108 | LLDB_INSTRUMENT_VA(this); |
1109 | |
1110 | ValueLocker locker; |
1111 | return GetSP(locker); |
1112 | } |
1113 | |
1114 | void SBValue::SetSP(ValueImplSP impl_sp) { m_opaque_sp = impl_sp; } |
1115 | |
1116 | void SBValue::SetSP(const lldb::ValueObjectSP &sp) { |
1117 | if (sp) { |
1118 | lldb::TargetSP target_sp(sp->GetTargetSP()); |
1119 | if (target_sp) { |
1120 | lldb::DynamicValueType use_dynamic = target_sp->GetPreferDynamicValue(); |
1121 | bool use_synthetic = |
1122 | target_sp->TargetProperties::GetEnableSyntheticValue(); |
1123 | m_opaque_sp = ValueImplSP(new ValueImpl(sp, use_dynamic, use_synthetic)); |
1124 | } else |
1125 | m_opaque_sp = ValueImplSP(new ValueImpl(sp, eNoDynamicValues, true)); |
1126 | } else |
1127 | m_opaque_sp = ValueImplSP(new ValueImpl(sp, eNoDynamicValues, false)); |
1128 | } |
1129 | |
1130 | void SBValue::SetSP(const lldb::ValueObjectSP &sp, |
1131 | lldb::DynamicValueType use_dynamic) { |
1132 | if (sp) { |
1133 | lldb::TargetSP target_sp(sp->GetTargetSP()); |
1134 | if (target_sp) { |
1135 | bool use_synthetic = |
1136 | target_sp->TargetProperties::GetEnableSyntheticValue(); |
1137 | SetSP(sp, use_dynamic, use_synthetic); |
1138 | } else |
1139 | SetSP(sp, use_dynamic, use_synthetic: true); |
1140 | } else |
1141 | SetSP(sp, use_dynamic, use_synthetic: false); |
1142 | } |
1143 | |
1144 | void SBValue::SetSP(const lldb::ValueObjectSP &sp, bool use_synthetic) { |
1145 | if (sp) { |
1146 | lldb::TargetSP target_sp(sp->GetTargetSP()); |
1147 | if (target_sp) { |
1148 | lldb::DynamicValueType use_dynamic = target_sp->GetPreferDynamicValue(); |
1149 | SetSP(sp, use_dynamic, use_synthetic); |
1150 | } else |
1151 | SetSP(sp, use_dynamic: eNoDynamicValues, use_synthetic); |
1152 | } else |
1153 | SetSP(sp, use_dynamic: eNoDynamicValues, use_synthetic); |
1154 | } |
1155 | |
1156 | void SBValue::SetSP(const lldb::ValueObjectSP &sp, |
1157 | lldb::DynamicValueType use_dynamic, bool use_synthetic) { |
1158 | m_opaque_sp = ValueImplSP(new ValueImpl(sp, use_dynamic, use_synthetic)); |
1159 | } |
1160 | |
1161 | void SBValue::SetSP(const lldb::ValueObjectSP &sp, |
1162 | lldb::DynamicValueType use_dynamic, bool use_synthetic, |
1163 | const char *name) { |
1164 | m_opaque_sp = |
1165 | ValueImplSP(new ValueImpl(sp, use_dynamic, use_synthetic, name)); |
1166 | } |
1167 | |
1168 | bool SBValue::GetExpressionPath(SBStream &description) { |
1169 | LLDB_INSTRUMENT_VA(this, description); |
1170 | |
1171 | ValueLocker locker; |
1172 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1173 | if (value_sp) { |
1174 | value_sp->GetExpressionPath(s&: description.ref()); |
1175 | return true; |
1176 | } |
1177 | return false; |
1178 | } |
1179 | |
1180 | bool SBValue::GetExpressionPath(SBStream &description, |
1181 | bool qualify_cxx_base_classes) { |
1182 | LLDB_INSTRUMENT_VA(this, description, qualify_cxx_base_classes); |
1183 | |
1184 | ValueLocker locker; |
1185 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1186 | if (value_sp) { |
1187 | value_sp->GetExpressionPath(s&: description.ref()); |
1188 | return true; |
1189 | } |
1190 | return false; |
1191 | } |
1192 | |
1193 | lldb::SBValue SBValue::EvaluateExpression(const char *expr) const { |
1194 | LLDB_INSTRUMENT_VA(this, expr); |
1195 | |
1196 | ValueLocker locker; |
1197 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1198 | if (!value_sp) |
1199 | return SBValue(); |
1200 | |
1201 | lldb::TargetSP target_sp = value_sp->GetTargetSP(); |
1202 | if (!target_sp) |
1203 | return SBValue(); |
1204 | |
1205 | lldb::SBExpressionOptions options; |
1206 | options.SetFetchDynamicValue(target_sp->GetPreferDynamicValue()); |
1207 | options.SetUnwindOnError(true); |
1208 | options.SetIgnoreBreakpoints(true); |
1209 | |
1210 | return EvaluateExpression(expr, options, name: nullptr); |
1211 | } |
1212 | |
1213 | lldb::SBValue |
1214 | SBValue::EvaluateExpression(const char *expr, |
1215 | const SBExpressionOptions &options) const { |
1216 | LLDB_INSTRUMENT_VA(this, expr, options); |
1217 | |
1218 | return EvaluateExpression(expr, options, name: nullptr); |
1219 | } |
1220 | |
1221 | lldb::SBValue SBValue::EvaluateExpression(const char *expr, |
1222 | const SBExpressionOptions &options, |
1223 | const char *name) const { |
1224 | LLDB_INSTRUMENT_VA(this, expr, options, name); |
1225 | |
1226 | if (!expr || expr[0] == '\0') { |
1227 | return SBValue(); |
1228 | } |
1229 | |
1230 | |
1231 | ValueLocker locker; |
1232 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1233 | if (!value_sp) { |
1234 | return SBValue(); |
1235 | } |
1236 | |
1237 | lldb::TargetSP target_sp = value_sp->GetTargetSP(); |
1238 | if (!target_sp) { |
1239 | return SBValue(); |
1240 | } |
1241 | |
1242 | std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex()); |
1243 | ExecutionContext exe_ctx(target_sp.get()); |
1244 | |
1245 | StackFrame *frame = exe_ctx.GetFramePtr(); |
1246 | if (!frame) { |
1247 | return SBValue(); |
1248 | } |
1249 | |
1250 | ValueObjectSP res_val_sp; |
1251 | target_sp->EvaluateExpression(expression: expr, exe_scope: frame, result_valobj_sp&: res_val_sp, options: options.ref(), fixed_expression: nullptr, |
1252 | ctx_obj: value_sp.get()); |
1253 | |
1254 | if (name) |
1255 | res_val_sp->SetName(ConstString(name)); |
1256 | |
1257 | SBValue result; |
1258 | result.SetSP(sp: res_val_sp, use_dynamic: options.GetFetchDynamicValue()); |
1259 | return result; |
1260 | } |
1261 | |
1262 | bool SBValue::GetDescription(SBStream &description) { |
1263 | LLDB_INSTRUMENT_VA(this, description); |
1264 | |
1265 | Stream &strm = description.ref(); |
1266 | |
1267 | ValueLocker locker; |
1268 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1269 | if (value_sp) { |
1270 | DumpValueObjectOptions options; |
1271 | options.SetUseDynamicType(m_opaque_sp->GetUseDynamic()); |
1272 | options.SetUseSyntheticValue(m_opaque_sp->GetUseSynthetic()); |
1273 | if (llvm::Error error = value_sp->Dump(s&: strm, options)) { |
1274 | strm << "error: "<< toString(E: std::move(error)); |
1275 | return false; |
1276 | } |
1277 | } else { |
1278 | strm.PutCString(cstr: "No value"); |
1279 | } |
1280 | |
1281 | return true; |
1282 | } |
1283 | |
1284 | lldb::Format SBValue::GetFormat() { |
1285 | LLDB_INSTRUMENT_VA(this); |
1286 | |
1287 | ValueLocker locker; |
1288 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1289 | if (value_sp) |
1290 | return value_sp->GetFormat(); |
1291 | return eFormatDefault; |
1292 | } |
1293 | |
1294 | void SBValue::SetFormat(lldb::Format format) { |
1295 | LLDB_INSTRUMENT_VA(this, format); |
1296 | |
1297 | ValueLocker locker; |
1298 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1299 | if (value_sp) |
1300 | value_sp->SetFormat(format); |
1301 | } |
1302 | |
1303 | lldb::SBValue SBValue::AddressOf() { |
1304 | LLDB_INSTRUMENT_VA(this); |
1305 | |
1306 | SBValue sb_value; |
1307 | ValueLocker locker; |
1308 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1309 | if (value_sp) { |
1310 | Status error; |
1311 | sb_value.SetSP(sp: value_sp->AddressOf(error), use_dynamic: GetPreferDynamicValue(), |
1312 | use_synthetic: GetPreferSyntheticValue()); |
1313 | } |
1314 | |
1315 | return sb_value; |
1316 | } |
1317 | |
1318 | lldb::addr_t SBValue::GetLoadAddress() { |
1319 | LLDB_INSTRUMENT_VA(this); |
1320 | |
1321 | lldb::addr_t value = LLDB_INVALID_ADDRESS; |
1322 | ValueLocker locker; |
1323 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1324 | if (value_sp) |
1325 | return value_sp->GetLoadAddress(); |
1326 | |
1327 | return value; |
1328 | } |
1329 | |
1330 | lldb::SBAddress SBValue::GetAddress() { |
1331 | LLDB_INSTRUMENT_VA(this); |
1332 | |
1333 | Address addr; |
1334 | ValueLocker locker; |
1335 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1336 | if (value_sp) { |
1337 | TargetSP target_sp(value_sp->GetTargetSP()); |
1338 | if (target_sp) { |
1339 | auto [value, addr_type] = |
1340 | value_sp->GetAddressOf(/*scalar_is_load_address=*/true); |
1341 | if (addr_type == eAddressTypeFile) { |
1342 | ModuleSP module_sp(value_sp->GetModule()); |
1343 | if (module_sp) |
1344 | module_sp->ResolveFileAddress(vm_addr: value, so_addr&: addr); |
1345 | } else if (addr_type == eAddressTypeLoad) { |
1346 | // no need to check the return value on this.. if it can actually do |
1347 | // the resolve addr will be in the form (section,offset), otherwise it |
1348 | // will simply be returned as (NULL, value) |
1349 | addr.SetLoadAddress(load_addr: value, target: target_sp.get()); |
1350 | } |
1351 | } |
1352 | } |
1353 | |
1354 | return SBAddress(addr); |
1355 | } |
1356 | |
1357 | lldb::SBData SBValue::GetPointeeData(uint32_t item_idx, uint32_t item_count) { |
1358 | LLDB_INSTRUMENT_VA(this, item_idx, item_count); |
1359 | |
1360 | lldb::SBData sb_data; |
1361 | ValueLocker locker; |
1362 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1363 | if (value_sp) { |
1364 | TargetSP target_sp(value_sp->GetTargetSP()); |
1365 | if (target_sp) { |
1366 | DataExtractorSP data_sp(new DataExtractor()); |
1367 | value_sp->GetPointeeData(data&: *data_sp, item_idx, item_count); |
1368 | if (data_sp->GetByteSize() > 0) |
1369 | *sb_data = data_sp; |
1370 | } |
1371 | } |
1372 | |
1373 | return sb_data; |
1374 | } |
1375 | |
1376 | lldb::SBData SBValue::GetData() { |
1377 | LLDB_INSTRUMENT_VA(this); |
1378 | |
1379 | lldb::SBData sb_data; |
1380 | ValueLocker locker; |
1381 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1382 | if (value_sp) { |
1383 | DataExtractorSP data_sp(new DataExtractor()); |
1384 | Status error; |
1385 | value_sp->GetData(data&: *data_sp, error); |
1386 | if (error.Success()) |
1387 | *sb_data = data_sp; |
1388 | } |
1389 | |
1390 | return sb_data; |
1391 | } |
1392 | |
1393 | bool SBValue::SetData(lldb::SBData &data, SBError &error) { |
1394 | LLDB_INSTRUMENT_VA(this, data, error); |
1395 | |
1396 | ValueLocker locker; |
1397 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1398 | bool ret = true; |
1399 | |
1400 | if (value_sp) { |
1401 | DataExtractor *data_extractor = data.get(); |
1402 | |
1403 | if (!data_extractor) { |
1404 | error = Status::FromErrorString(str: "No data to set"); |
1405 | ret = false; |
1406 | } else { |
1407 | Status set_error; |
1408 | |
1409 | value_sp->SetData(data&: *data_extractor, error&: set_error); |
1410 | |
1411 | if (!set_error.Success()) { |
1412 | error = Status::FromErrorStringWithFormat(format: "Couldn't set data: %s", |
1413 | set_error.AsCString()); |
1414 | ret = false; |
1415 | } |
1416 | } |
1417 | } else { |
1418 | error = Status::FromErrorStringWithFormat( |
1419 | format: "Couldn't set data: could not get SBValue: %s", |
1420 | locker.GetError().AsCString()); |
1421 | ret = false; |
1422 | } |
1423 | |
1424 | return ret; |
1425 | } |
1426 | |
1427 | lldb::SBValue SBValue::Clone(const char *new_name) { |
1428 | LLDB_INSTRUMENT_VA(this, new_name); |
1429 | |
1430 | ValueLocker locker; |
1431 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1432 | |
1433 | if (value_sp) |
1434 | return lldb::SBValue(value_sp->Clone(new_name: ConstString(new_name))); |
1435 | else |
1436 | return lldb::SBValue(); |
1437 | } |
1438 | |
1439 | lldb::SBDeclaration SBValue::GetDeclaration() { |
1440 | LLDB_INSTRUMENT_VA(this); |
1441 | |
1442 | ValueLocker locker; |
1443 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1444 | SBDeclaration decl_sb; |
1445 | if (value_sp) { |
1446 | Declaration decl; |
1447 | if (value_sp->GetDeclaration(decl)) |
1448 | decl_sb.SetDeclaration(decl); |
1449 | } |
1450 | return decl_sb; |
1451 | } |
1452 | |
1453 | lldb::SBWatchpoint SBValue::Watch(bool resolve_location, bool read, bool write, |
1454 | SBError &error) { |
1455 | LLDB_INSTRUMENT_VA(this, resolve_location, read, write, error); |
1456 | |
1457 | SBWatchpoint sb_watchpoint; |
1458 | |
1459 | // If the SBValue is not valid, there's no point in even trying to watch it. |
1460 | ValueLocker locker; |
1461 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1462 | TargetSP target_sp(GetTarget().GetSP()); |
1463 | if (value_sp && target_sp) { |
1464 | // Read and Write cannot both be false. |
1465 | if (!read && !write) |
1466 | return sb_watchpoint; |
1467 | |
1468 | // If the value is not in scope, don't try and watch and invalid value |
1469 | if (!IsInScope()) |
1470 | return sb_watchpoint; |
1471 | |
1472 | addr_t addr = GetLoadAddress(); |
1473 | if (addr == LLDB_INVALID_ADDRESS) |
1474 | return sb_watchpoint; |
1475 | size_t byte_size = GetByteSize(); |
1476 | if (byte_size == 0) |
1477 | return sb_watchpoint; |
1478 | |
1479 | uint32_t watch_type = 0; |
1480 | if (read) { |
1481 | watch_type |= LLDB_WATCH_TYPE_READ; |
1482 | // read + write, the most likely intention |
1483 | // is to catch all writes to this, not just |
1484 | // value modifications. |
1485 | if (write) |
1486 | watch_type |= LLDB_WATCH_TYPE_WRITE; |
1487 | } else { |
1488 | if (write) |
1489 | watch_type |= LLDB_WATCH_TYPE_MODIFY; |
1490 | } |
1491 | |
1492 | Status rc; |
1493 | CompilerType type(value_sp->GetCompilerType()); |
1494 | WatchpointSP watchpoint_sp = |
1495 | target_sp->CreateWatchpoint(addr, size: byte_size, type: &type, kind: watch_type, error&: rc); |
1496 | error.SetError(std::move(rc)); |
1497 | |
1498 | if (watchpoint_sp) { |
1499 | sb_watchpoint.SetSP(watchpoint_sp); |
1500 | Declaration decl; |
1501 | if (value_sp->GetDeclaration(decl)) { |
1502 | if (decl.GetFile()) { |
1503 | StreamString ss; |
1504 | // True to show fullpath for declaration file. |
1505 | decl.DumpStopContext(s: &ss, show_fullpaths: true); |
1506 | watchpoint_sp->SetDeclInfo(std::string(ss.GetString())); |
1507 | } |
1508 | } |
1509 | } |
1510 | } else if (target_sp) { |
1511 | error = Status::FromErrorStringWithFormat(format: "could not get SBValue: %s", |
1512 | locker.GetError().AsCString()); |
1513 | } else { |
1514 | error = Status::FromErrorString( |
1515 | str: "could not set watchpoint, a target is required"); |
1516 | } |
1517 | |
1518 | return sb_watchpoint; |
1519 | } |
1520 | |
1521 | // FIXME: Remove this method impl (as well as the decl in .h) once it is no |
1522 | // longer needed. |
1523 | // Backward compatibility fix in the interim. |
1524 | lldb::SBWatchpoint SBValue::Watch(bool resolve_location, bool read, |
1525 | bool write) { |
1526 | LLDB_INSTRUMENT_VA(this, resolve_location, read, write); |
1527 | |
1528 | SBError error; |
1529 | return Watch(resolve_location, read, write, error); |
1530 | } |
1531 | |
1532 | lldb::SBWatchpoint SBValue::WatchPointee(bool resolve_location, bool read, |
1533 | bool write, SBError &error) { |
1534 | LLDB_INSTRUMENT_VA(this, resolve_location, read, write, error); |
1535 | |
1536 | SBWatchpoint sb_watchpoint; |
1537 | if (IsInScope() && GetType().IsPointerType()) |
1538 | sb_watchpoint = Dereference().Watch(resolve_location, read, write, error); |
1539 | return sb_watchpoint; |
1540 | } |
1541 | |
1542 | lldb::SBValue SBValue::Persist() { |
1543 | LLDB_INSTRUMENT_VA(this); |
1544 | |
1545 | ValueLocker locker; |
1546 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1547 | SBValue persisted_sb; |
1548 | if (value_sp) { |
1549 | persisted_sb.SetSP(value_sp->Persist()); |
1550 | } |
1551 | return persisted_sb; |
1552 | } |
1553 | |
1554 | lldb::SBValue SBValue::GetVTable() { |
1555 | SBValue vtable_sb; |
1556 | ValueLocker locker; |
1557 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1558 | if (!value_sp) |
1559 | return vtable_sb; |
1560 | |
1561 | vtable_sb.SetSP(value_sp->GetVTable()); |
1562 | return vtable_sb; |
1563 | } |
1564 |
Definitions
- ValueImpl
- ValueImpl
- ValueImpl
- ValueImpl
- operator=
- IsValid
- GetRootSP
- GetSP
- SetUseDynamic
- SetUseSynthetic
- GetUseDynamic
- GetUseSynthetic
- GetTargetSP
- GetProcessSP
- GetThreadSP
- GetFrameSP
- ValueLocker
- ValueLocker
- GetLockedSP
- GetError
- SBValue
- SBValue
- SBValue
- operator=
- ~SBValue
- IsValid
- operator bool
- Clear
- GetError
- GetID
- GetName
- GetTypeName
- GetDisplayTypeName
- GetByteSize
- IsInScope
- GetValue
- GetValueType
- GetObjectDescription
- GetType
- GetValueDidChange
- GetSummary
- GetSummary
- GetLocation
- SetValueFromCString
- SetValueFromCString
- GetTypeFormat
- GetTypeSummary
- GetTypeFilter
- GetTypeSynthetic
- CreateChildAtOffset
- Cast
- CreateValueFromExpression
- CreateValueFromExpression
- CreateValueFromAddress
- CreateValueFromData
- CreateBoolValue
- GetChildAtIndex
- GetChildAtIndex
- GetIndexOfChildWithName
- GetChildMemberWithName
- GetChildMemberWithName
- GetDynamicValue
- GetStaticValue
- GetNonSyntheticValue
- GetSyntheticValue
- GetPreferDynamicValue
- SetPreferDynamicValue
- GetPreferSyntheticValue
- SetPreferSyntheticValue
- IsDynamic
- IsSynthetic
- IsSyntheticChildrenGenerated
- SetSyntheticChildrenGenerated
- GetValueForExpressionPath
- GetValueAsSigned
- GetValueAsUnsigned
- GetValueAsSigned
- GetValueAsUnsigned
- GetValueAsAddress
- MightHaveChildren
- IsRuntimeSupportValue
- GetNumChildren
- GetNumChildren
- Dereference
- TypeIsPointerType
- GetOpaqueType
- GetTarget
- GetProcess
- GetThread
- GetFrame
- GetSP
- GetSP
- SetSP
- SetSP
- SetSP
- SetSP
- SetSP
- SetSP
- GetExpressionPath
- GetExpressionPath
- EvaluateExpression
- EvaluateExpression
- EvaluateExpression
- GetDescription
- GetFormat
- SetFormat
- AddressOf
- GetLoadAddress
- GetAddress
- GetPointeeData
- GetData
- SetData
- Clone
- GetDeclaration
- Watch
- Watch
- WatchPointee
- Persist
Learn to use CMake with our Intro Training
Find out more