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/Core/ValueObject.h" |
25 | #include "lldb/Core/ValueObjectConstResult.h" |
26 | #include "lldb/DataFormatters/DataVisualization.h" |
27 | #include "lldb/DataFormatters/DumpValueObjectOptions.h" |
28 | #include "lldb/Symbol/Block.h" |
29 | #include "lldb/Symbol/ObjectFile.h" |
30 | #include "lldb/Symbol/Type.h" |
31 | #include "lldb/Symbol/Variable.h" |
32 | #include "lldb/Symbol/VariableList.h" |
33 | #include "lldb/Target/ExecutionContext.h" |
34 | #include "lldb/Target/Process.h" |
35 | #include "lldb/Target/StackFrame.h" |
36 | #include "lldb/Target/Target.h" |
37 | #include "lldb/Target/Thread.h" |
38 | #include "lldb/Utility/DataExtractor.h" |
39 | #include "lldb/Utility/Scalar.h" |
40 | #include "lldb/Utility/Stream.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.SetErrorString("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.SetErrorString("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.SetErrorString("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()); |
274 | else |
275 | sb_error.SetErrorStringWithFormat("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 = 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 | return ConstString(value_sp->GetObjectDescription()).GetCString(); |
383 | } |
384 | |
385 | SBType SBValue::GetType() { |
386 | LLDB_INSTRUMENT_VA(this); |
387 | |
388 | SBType sb_type; |
389 | ValueLocker locker; |
390 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
391 | TypeImplSP type_sp; |
392 | if (value_sp) { |
393 | type_sp = std::make_shared<TypeImpl>(args: value_sp->GetTypeImpl()); |
394 | sb_type.SetSP(type_sp); |
395 | } |
396 | |
397 | return sb_type; |
398 | } |
399 | |
400 | bool SBValue::GetValueDidChange() { |
401 | LLDB_INSTRUMENT_VA(this); |
402 | |
403 | bool result = false; |
404 | ValueLocker locker; |
405 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
406 | if (value_sp) { |
407 | if (value_sp->UpdateValueIfNeeded(update_format: false)) |
408 | result = value_sp->GetValueDidChange(); |
409 | } |
410 | |
411 | return result; |
412 | } |
413 | |
414 | const char *SBValue::GetSummary() { |
415 | LLDB_INSTRUMENT_VA(this); |
416 | |
417 | ValueLocker locker; |
418 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
419 | if (!value_sp) |
420 | return nullptr; |
421 | |
422 | return ConstString(value_sp->GetSummaryAsCString()).GetCString(); |
423 | } |
424 | |
425 | const char *SBValue::GetSummary(lldb::SBStream &stream, |
426 | lldb::SBTypeSummaryOptions &options) { |
427 | LLDB_INSTRUMENT_VA(this, stream, options); |
428 | |
429 | ValueLocker locker; |
430 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
431 | if (value_sp) { |
432 | std::string buffer; |
433 | if (value_sp->GetSummaryAsCString(destination&: buffer, options: options.ref()) && !buffer.empty()) |
434 | stream.Printf(format: "%s" , buffer.c_str()); |
435 | } |
436 | return ConstString(stream.GetData()).GetCString(); |
437 | } |
438 | |
439 | const char *SBValue::GetLocation() { |
440 | LLDB_INSTRUMENT_VA(this); |
441 | |
442 | ValueLocker locker; |
443 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
444 | if (!value_sp) |
445 | return nullptr; |
446 | |
447 | return ConstString(value_sp->GetLocationAsCString()).GetCString(); |
448 | } |
449 | |
450 | // Deprecated - use the one that takes an lldb::SBError |
451 | bool SBValue::SetValueFromCString(const char *value_str) { |
452 | LLDB_INSTRUMENT_VA(this, value_str); |
453 | |
454 | lldb::SBError dummy; |
455 | return SetValueFromCString(value_str, error&: dummy); |
456 | } |
457 | |
458 | bool SBValue::SetValueFromCString(const char *value_str, lldb::SBError &error) { |
459 | LLDB_INSTRUMENT_VA(this, value_str, error); |
460 | |
461 | bool success = false; |
462 | ValueLocker locker; |
463 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
464 | if (value_sp) { |
465 | success = value_sp->SetValueFromCString(value_str, error&: error.ref()); |
466 | } else |
467 | error.SetErrorStringWithFormat("Could not get value: %s" , |
468 | locker.GetError().AsCString()); |
469 | |
470 | return success; |
471 | } |
472 | |
473 | lldb::SBTypeFormat SBValue::GetTypeFormat() { |
474 | LLDB_INSTRUMENT_VA(this); |
475 | |
476 | lldb::SBTypeFormat format; |
477 | ValueLocker locker; |
478 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
479 | if (value_sp) { |
480 | if (value_sp->UpdateValueIfNeeded(update_format: true)) { |
481 | lldb::TypeFormatImplSP format_sp = value_sp->GetValueFormat(); |
482 | if (format_sp) |
483 | format.SetSP(format_sp); |
484 | } |
485 | } |
486 | return format; |
487 | } |
488 | |
489 | lldb::SBTypeSummary SBValue::GetTypeSummary() { |
490 | LLDB_INSTRUMENT_VA(this); |
491 | |
492 | lldb::SBTypeSummary summary; |
493 | ValueLocker locker; |
494 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
495 | if (value_sp) { |
496 | if (value_sp->UpdateValueIfNeeded(update_format: true)) { |
497 | lldb::TypeSummaryImplSP summary_sp = value_sp->GetSummaryFormat(); |
498 | if (summary_sp) |
499 | summary.SetSP(summary_sp); |
500 | } |
501 | } |
502 | return summary; |
503 | } |
504 | |
505 | lldb::SBTypeFilter SBValue::GetTypeFilter() { |
506 | LLDB_INSTRUMENT_VA(this); |
507 | |
508 | lldb::SBTypeFilter filter; |
509 | ValueLocker locker; |
510 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
511 | if (value_sp) { |
512 | if (value_sp->UpdateValueIfNeeded(update_format: true)) { |
513 | lldb::SyntheticChildrenSP synthetic_sp = value_sp->GetSyntheticChildren(); |
514 | |
515 | if (synthetic_sp && !synthetic_sp->IsScripted()) { |
516 | TypeFilterImplSP filter_sp = |
517 | std::static_pointer_cast<TypeFilterImpl>(r: synthetic_sp); |
518 | filter.SetSP(filter_sp); |
519 | } |
520 | } |
521 | } |
522 | return filter; |
523 | } |
524 | |
525 | lldb::SBTypeSynthetic SBValue::GetTypeSynthetic() { |
526 | LLDB_INSTRUMENT_VA(this); |
527 | |
528 | lldb::SBTypeSynthetic synthetic; |
529 | ValueLocker locker; |
530 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
531 | if (value_sp) { |
532 | if (value_sp->UpdateValueIfNeeded(update_format: true)) { |
533 | lldb::SyntheticChildrenSP children_sp = value_sp->GetSyntheticChildren(); |
534 | |
535 | if (children_sp && children_sp->IsScripted()) { |
536 | ScriptedSyntheticChildrenSP synth_sp = |
537 | std::static_pointer_cast<ScriptedSyntheticChildren>(r: children_sp); |
538 | synthetic.SetSP(synth_sp); |
539 | } |
540 | } |
541 | } |
542 | return synthetic; |
543 | } |
544 | |
545 | lldb::SBValue SBValue::CreateChildAtOffset(const char *name, uint32_t offset, |
546 | SBType type) { |
547 | LLDB_INSTRUMENT_VA(this, name, offset, type); |
548 | |
549 | lldb::SBValue sb_value; |
550 | ValueLocker locker; |
551 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
552 | lldb::ValueObjectSP new_value_sp; |
553 | if (value_sp) { |
554 | TypeImplSP type_sp(type.GetSP()); |
555 | if (type.IsValid()) { |
556 | sb_value.SetSP(sp: value_sp->GetSyntheticChildAtOffset( |
557 | offset, type: type_sp->GetCompilerType(prefer_dynamic: false), can_create: true), |
558 | use_dynamic: GetPreferDynamicValue(), use_synthetic: GetPreferSyntheticValue(), name); |
559 | } |
560 | } |
561 | return sb_value; |
562 | } |
563 | |
564 | lldb::SBValue SBValue::Cast(SBType type) { |
565 | LLDB_INSTRUMENT_VA(this, type); |
566 | |
567 | lldb::SBValue sb_value; |
568 | ValueLocker locker; |
569 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
570 | TypeImplSP type_sp(type.GetSP()); |
571 | if (value_sp && type_sp) |
572 | sb_value.SetSP(sp: value_sp->Cast(compiler_type: type_sp->GetCompilerType(prefer_dynamic: false)), |
573 | use_dynamic: GetPreferDynamicValue(), use_synthetic: GetPreferSyntheticValue()); |
574 | return sb_value; |
575 | } |
576 | |
577 | lldb::SBValue SBValue::CreateValueFromExpression(const char *name, |
578 | const char *expression) { |
579 | LLDB_INSTRUMENT_VA(this, name, expression); |
580 | |
581 | SBExpressionOptions options; |
582 | options.ref().SetKeepInMemory(true); |
583 | return CreateValueFromExpression(name, expression, options); |
584 | } |
585 | |
586 | lldb::SBValue SBValue::CreateValueFromExpression(const char *name, |
587 | const char *expression, |
588 | SBExpressionOptions &options) { |
589 | LLDB_INSTRUMENT_VA(this, name, expression, options); |
590 | |
591 | lldb::SBValue sb_value; |
592 | ValueLocker locker; |
593 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
594 | lldb::ValueObjectSP new_value_sp; |
595 | if (value_sp) { |
596 | ExecutionContext exe_ctx(value_sp->GetExecutionContextRef()); |
597 | new_value_sp = ValueObject::CreateValueObjectFromExpression( |
598 | name, expression, exe_ctx, options: options.ref()); |
599 | if (new_value_sp) |
600 | new_value_sp->SetName(ConstString(name)); |
601 | } |
602 | sb_value.SetSP(new_value_sp); |
603 | return sb_value; |
604 | } |
605 | |
606 | lldb::SBValue SBValue::CreateValueFromAddress(const char *name, |
607 | lldb::addr_t address, |
608 | SBType sb_type) { |
609 | LLDB_INSTRUMENT_VA(this, name, address, sb_type); |
610 | |
611 | lldb::SBValue sb_value; |
612 | ValueLocker locker; |
613 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
614 | lldb::ValueObjectSP new_value_sp; |
615 | lldb::TypeImplSP type_impl_sp(sb_type.GetSP()); |
616 | if (value_sp && type_impl_sp) { |
617 | CompilerType ast_type(type_impl_sp->GetCompilerType(prefer_dynamic: true)); |
618 | ExecutionContext exe_ctx(value_sp->GetExecutionContextRef()); |
619 | new_value_sp = ValueObject::CreateValueObjectFromAddress(name, address, |
620 | exe_ctx, type: ast_type); |
621 | } |
622 | sb_value.SetSP(new_value_sp); |
623 | return sb_value; |
624 | } |
625 | |
626 | lldb::SBValue SBValue::CreateValueFromData(const char *name, SBData data, |
627 | SBType sb_type) { |
628 | LLDB_INSTRUMENT_VA(this, name, data, sb_type); |
629 | |
630 | lldb::SBValue sb_value; |
631 | lldb::ValueObjectSP new_value_sp; |
632 | ValueLocker locker; |
633 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
634 | lldb::TypeImplSP type_impl_sp(sb_type.GetSP()); |
635 | if (value_sp && type_impl_sp) { |
636 | ExecutionContext exe_ctx(value_sp->GetExecutionContextRef()); |
637 | new_value_sp = ValueObject::CreateValueObjectFromData( |
638 | name, data: **data, exe_ctx, type: type_impl_sp->GetCompilerType(prefer_dynamic: true)); |
639 | new_value_sp->SetAddressTypeOfChildren(eAddressTypeLoad); |
640 | } |
641 | sb_value.SetSP(new_value_sp); |
642 | return sb_value; |
643 | } |
644 | |
645 | SBValue SBValue::GetChildAtIndex(uint32_t idx) { |
646 | LLDB_INSTRUMENT_VA(this, idx); |
647 | |
648 | const bool can_create_synthetic = false; |
649 | lldb::DynamicValueType use_dynamic = eNoDynamicValues; |
650 | TargetSP target_sp; |
651 | if (m_opaque_sp) |
652 | target_sp = m_opaque_sp->GetTargetSP(); |
653 | |
654 | if (target_sp) |
655 | use_dynamic = target_sp->GetPreferDynamicValue(); |
656 | |
657 | return GetChildAtIndex(idx, use_dynamic, can_create_synthetic); |
658 | } |
659 | |
660 | SBValue SBValue::GetChildAtIndex(uint32_t idx, |
661 | lldb::DynamicValueType use_dynamic, |
662 | bool can_create_synthetic) { |
663 | LLDB_INSTRUMENT_VA(this, idx, use_dynamic, can_create_synthetic); |
664 | |
665 | lldb::ValueObjectSP child_sp; |
666 | |
667 | ValueLocker locker; |
668 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
669 | if (value_sp) { |
670 | const bool can_create = true; |
671 | child_sp = value_sp->GetChildAtIndex(idx); |
672 | if (can_create_synthetic && !child_sp) { |
673 | child_sp = value_sp->GetSyntheticArrayMember(index: idx, can_create); |
674 | } |
675 | } |
676 | |
677 | SBValue sb_value; |
678 | sb_value.SetSP(sp: child_sp, use_dynamic, use_synthetic: GetPreferSyntheticValue()); |
679 | |
680 | return sb_value; |
681 | } |
682 | |
683 | uint32_t SBValue::GetIndexOfChildWithName(const char *name) { |
684 | LLDB_INSTRUMENT_VA(this, name); |
685 | |
686 | uint32_t idx = UINT32_MAX; |
687 | ValueLocker locker; |
688 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
689 | if (value_sp) { |
690 | idx = value_sp->GetIndexOfChildWithName(name); |
691 | } |
692 | return idx; |
693 | } |
694 | |
695 | SBValue SBValue::GetChildMemberWithName(const char *name) { |
696 | LLDB_INSTRUMENT_VA(this, name); |
697 | |
698 | lldb::DynamicValueType use_dynamic_value = eNoDynamicValues; |
699 | TargetSP target_sp; |
700 | if (m_opaque_sp) |
701 | target_sp = m_opaque_sp->GetTargetSP(); |
702 | |
703 | if (target_sp) |
704 | use_dynamic_value = target_sp->GetPreferDynamicValue(); |
705 | return GetChildMemberWithName(name, use_dynamic: use_dynamic_value); |
706 | } |
707 | |
708 | SBValue |
709 | SBValue::GetChildMemberWithName(const char *name, |
710 | lldb::DynamicValueType use_dynamic_value) { |
711 | LLDB_INSTRUMENT_VA(this, name, use_dynamic_value); |
712 | |
713 | lldb::ValueObjectSP child_sp; |
714 | |
715 | ValueLocker locker; |
716 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
717 | if (value_sp) { |
718 | child_sp = value_sp->GetChildMemberWithName(name); |
719 | } |
720 | |
721 | SBValue sb_value; |
722 | sb_value.SetSP(sp: child_sp, use_dynamic: use_dynamic_value, use_synthetic: GetPreferSyntheticValue()); |
723 | |
724 | return sb_value; |
725 | } |
726 | |
727 | lldb::SBValue SBValue::GetDynamicValue(lldb::DynamicValueType use_dynamic) { |
728 | LLDB_INSTRUMENT_VA(this, use_dynamic); |
729 | |
730 | SBValue value_sb; |
731 | if (IsValid()) { |
732 | ValueImplSP proxy_sp(new ValueImpl(m_opaque_sp->GetRootSP(), use_dynamic, |
733 | m_opaque_sp->GetUseSynthetic())); |
734 | value_sb.SetSP(proxy_sp); |
735 | } |
736 | return value_sb; |
737 | } |
738 | |
739 | lldb::SBValue SBValue::GetStaticValue() { |
740 | LLDB_INSTRUMENT_VA(this); |
741 | |
742 | SBValue value_sb; |
743 | if (IsValid()) { |
744 | ValueImplSP proxy_sp(new ValueImpl(m_opaque_sp->GetRootSP(), |
745 | eNoDynamicValues, |
746 | m_opaque_sp->GetUseSynthetic())); |
747 | value_sb.SetSP(proxy_sp); |
748 | } |
749 | return value_sb; |
750 | } |
751 | |
752 | lldb::SBValue SBValue::GetNonSyntheticValue() { |
753 | LLDB_INSTRUMENT_VA(this); |
754 | |
755 | SBValue value_sb; |
756 | if (IsValid()) { |
757 | ValueImplSP proxy_sp(new ValueImpl(m_opaque_sp->GetRootSP(), |
758 | m_opaque_sp->GetUseDynamic(), false)); |
759 | value_sb.SetSP(proxy_sp); |
760 | } |
761 | return value_sb; |
762 | } |
763 | |
764 | lldb::DynamicValueType SBValue::GetPreferDynamicValue() { |
765 | LLDB_INSTRUMENT_VA(this); |
766 | |
767 | if (!IsValid()) |
768 | return eNoDynamicValues; |
769 | return m_opaque_sp->GetUseDynamic(); |
770 | } |
771 | |
772 | void SBValue::SetPreferDynamicValue(lldb::DynamicValueType use_dynamic) { |
773 | LLDB_INSTRUMENT_VA(this, use_dynamic); |
774 | |
775 | if (IsValid()) |
776 | return m_opaque_sp->SetUseDynamic(use_dynamic); |
777 | } |
778 | |
779 | bool SBValue::GetPreferSyntheticValue() { |
780 | LLDB_INSTRUMENT_VA(this); |
781 | |
782 | if (!IsValid()) |
783 | return false; |
784 | return m_opaque_sp->GetUseSynthetic(); |
785 | } |
786 | |
787 | void SBValue::SetPreferSyntheticValue(bool use_synthetic) { |
788 | LLDB_INSTRUMENT_VA(this, use_synthetic); |
789 | |
790 | if (IsValid()) |
791 | return m_opaque_sp->SetUseSynthetic(use_synthetic); |
792 | } |
793 | |
794 | bool SBValue::IsDynamic() { |
795 | LLDB_INSTRUMENT_VA(this); |
796 | |
797 | ValueLocker locker; |
798 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
799 | if (value_sp) |
800 | return value_sp->IsDynamic(); |
801 | return false; |
802 | } |
803 | |
804 | bool SBValue::IsSynthetic() { |
805 | LLDB_INSTRUMENT_VA(this); |
806 | |
807 | ValueLocker locker; |
808 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
809 | if (value_sp) |
810 | return value_sp->IsSynthetic(); |
811 | return false; |
812 | } |
813 | |
814 | bool SBValue::IsSyntheticChildrenGenerated() { |
815 | LLDB_INSTRUMENT_VA(this); |
816 | |
817 | ValueLocker locker; |
818 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
819 | if (value_sp) |
820 | return value_sp->IsSyntheticChildrenGenerated(); |
821 | return false; |
822 | } |
823 | |
824 | void SBValue::SetSyntheticChildrenGenerated(bool is) { |
825 | LLDB_INSTRUMENT_VA(this, is); |
826 | |
827 | ValueLocker locker; |
828 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
829 | if (value_sp) |
830 | return value_sp->SetSyntheticChildrenGenerated(is); |
831 | } |
832 | |
833 | lldb::SBValue SBValue::GetValueForExpressionPath(const char *expr_path) { |
834 | LLDB_INSTRUMENT_VA(this, expr_path); |
835 | |
836 | lldb::ValueObjectSP child_sp; |
837 | ValueLocker locker; |
838 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
839 | if (value_sp) { |
840 | // using default values for all the fancy options, just do it if you can |
841 | child_sp = value_sp->GetValueForExpressionPath(expression: expr_path); |
842 | } |
843 | |
844 | SBValue sb_value; |
845 | sb_value.SetSP(sp: child_sp, use_dynamic: GetPreferDynamicValue(), use_synthetic: GetPreferSyntheticValue()); |
846 | |
847 | return sb_value; |
848 | } |
849 | |
850 | int64_t SBValue::GetValueAsSigned(SBError &error, int64_t fail_value) { |
851 | LLDB_INSTRUMENT_VA(this, error, fail_value); |
852 | |
853 | error.Clear(); |
854 | ValueLocker locker; |
855 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
856 | if (value_sp) { |
857 | bool success = true; |
858 | uint64_t ret_val = fail_value; |
859 | ret_val = value_sp->GetValueAsSigned(fail_value, success: &success); |
860 | if (!success) |
861 | error.SetErrorString("could not resolve value" ); |
862 | return ret_val; |
863 | } else |
864 | error.SetErrorStringWithFormat("could not get SBValue: %s" , |
865 | locker.GetError().AsCString()); |
866 | |
867 | return fail_value; |
868 | } |
869 | |
870 | uint64_t SBValue::GetValueAsUnsigned(SBError &error, uint64_t fail_value) { |
871 | LLDB_INSTRUMENT_VA(this, error, fail_value); |
872 | |
873 | error.Clear(); |
874 | ValueLocker locker; |
875 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
876 | if (value_sp) { |
877 | bool success = true; |
878 | uint64_t ret_val = fail_value; |
879 | ret_val = value_sp->GetValueAsUnsigned(fail_value, success: &success); |
880 | if (!success) |
881 | error.SetErrorString("could not resolve value" ); |
882 | return ret_val; |
883 | } else |
884 | error.SetErrorStringWithFormat("could not get SBValue: %s" , |
885 | locker.GetError().AsCString()); |
886 | |
887 | return fail_value; |
888 | } |
889 | |
890 | int64_t SBValue::GetValueAsSigned(int64_t fail_value) { |
891 | LLDB_INSTRUMENT_VA(this, fail_value); |
892 | |
893 | ValueLocker locker; |
894 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
895 | if (value_sp) { |
896 | return value_sp->GetValueAsSigned(fail_value); |
897 | } |
898 | return fail_value; |
899 | } |
900 | |
901 | uint64_t SBValue::GetValueAsUnsigned(uint64_t fail_value) { |
902 | LLDB_INSTRUMENT_VA(this, fail_value); |
903 | |
904 | ValueLocker locker; |
905 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
906 | if (value_sp) { |
907 | return value_sp->GetValueAsUnsigned(fail_value); |
908 | } |
909 | return fail_value; |
910 | } |
911 | |
912 | bool SBValue::MightHaveChildren() { |
913 | LLDB_INSTRUMENT_VA(this); |
914 | |
915 | bool has_children = false; |
916 | ValueLocker locker; |
917 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
918 | if (value_sp) |
919 | has_children = value_sp->MightHaveChildren(); |
920 | |
921 | return has_children; |
922 | } |
923 | |
924 | bool SBValue::IsRuntimeSupportValue() { |
925 | LLDB_INSTRUMENT_VA(this); |
926 | |
927 | bool is_support = false; |
928 | ValueLocker locker; |
929 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
930 | if (value_sp) |
931 | is_support = value_sp->IsRuntimeSupportValue(); |
932 | |
933 | return is_support; |
934 | } |
935 | |
936 | uint32_t SBValue::GetNumChildren() { |
937 | LLDB_INSTRUMENT_VA(this); |
938 | |
939 | return GetNumChildren(UINT32_MAX); |
940 | } |
941 | |
942 | uint32_t SBValue::GetNumChildren(uint32_t max) { |
943 | LLDB_INSTRUMENT_VA(this, max); |
944 | |
945 | uint32_t num_children = 0; |
946 | |
947 | ValueLocker locker; |
948 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
949 | if (value_sp) |
950 | num_children = value_sp->GetNumChildrenIgnoringErrors(max); |
951 | |
952 | return num_children; |
953 | } |
954 | |
955 | SBValue SBValue::Dereference() { |
956 | LLDB_INSTRUMENT_VA(this); |
957 | |
958 | SBValue sb_value; |
959 | ValueLocker locker; |
960 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
961 | if (value_sp) { |
962 | Status error; |
963 | sb_value = value_sp->Dereference(error); |
964 | } |
965 | |
966 | return sb_value; |
967 | } |
968 | |
969 | // Deprecated - please use GetType().IsPointerType() instead. |
970 | bool SBValue::TypeIsPointerType() { |
971 | LLDB_INSTRUMENT_VA(this); |
972 | |
973 | return GetType().IsPointerType(); |
974 | } |
975 | |
976 | void *SBValue::GetOpaqueType() { |
977 | LLDB_INSTRUMENT_VA(this); |
978 | |
979 | ValueLocker locker; |
980 | lldb::ValueObjectSP value_sp(GetSP(value_locker&: locker)); |
981 | if (value_sp) |
982 | return value_sp->GetCompilerType().GetOpaqueQualType(); |
983 | return nullptr; |
984 | } |
985 | |
986 | lldb::SBTarget SBValue::GetTarget() { |
987 | LLDB_INSTRUMENT_VA(this); |
988 | |
989 | SBTarget sb_target; |
990 | TargetSP target_sp; |
991 | if (m_opaque_sp) { |
992 | target_sp = m_opaque_sp->GetTargetSP(); |
993 | sb_target.SetSP(target_sp); |
994 | } |
995 | |
996 | return sb_target; |
997 | } |
998 | |
999 | lldb::SBProcess SBValue::GetProcess() { |
1000 | LLDB_INSTRUMENT_VA(this); |
1001 | |
1002 | SBProcess sb_process; |
1003 | ProcessSP process_sp; |
1004 | if (m_opaque_sp) { |
1005 | process_sp = m_opaque_sp->GetProcessSP(); |
1006 | sb_process.SetSP(process_sp); |
1007 | } |
1008 | |
1009 | return sb_process; |
1010 | } |
1011 | |
1012 | lldb::SBThread SBValue::GetThread() { |
1013 | LLDB_INSTRUMENT_VA(this); |
1014 | |
1015 | SBThread sb_thread; |
1016 | ThreadSP thread_sp; |
1017 | if (m_opaque_sp) { |
1018 | thread_sp = m_opaque_sp->GetThreadSP(); |
1019 | sb_thread.SetThread(thread_sp); |
1020 | } |
1021 | |
1022 | return sb_thread; |
1023 | } |
1024 | |
1025 | lldb::SBFrame SBValue::GetFrame() { |
1026 | LLDB_INSTRUMENT_VA(this); |
1027 | |
1028 | SBFrame sb_frame; |
1029 | StackFrameSP frame_sp; |
1030 | if (m_opaque_sp) { |
1031 | frame_sp = m_opaque_sp->GetFrameSP(); |
1032 | sb_frame.SetFrameSP(frame_sp); |
1033 | } |
1034 | |
1035 | return sb_frame; |
1036 | } |
1037 | |
1038 | lldb::ValueObjectSP SBValue::GetSP(ValueLocker &locker) const { |
1039 | // IsValid means that the SBValue has a value in it. But that's not the |
1040 | // only time that ValueObjects are useful. We also want to return the value |
1041 | // if there's an error state in it. |
1042 | if (!m_opaque_sp || (!m_opaque_sp->IsValid() |
1043 | && (m_opaque_sp->GetRootSP() |
1044 | && !m_opaque_sp->GetRootSP()->GetError().Fail()))) { |
1045 | locker.GetError().SetErrorString("No value" ); |
1046 | return ValueObjectSP(); |
1047 | } |
1048 | return locker.GetLockedSP(in_value&: *m_opaque_sp.get()); |
1049 | } |
1050 | |
1051 | lldb::ValueObjectSP SBValue::GetSP() const { |
1052 | LLDB_INSTRUMENT_VA(this); |
1053 | |
1054 | ValueLocker locker; |
1055 | return GetSP(locker); |
1056 | } |
1057 | |
1058 | void SBValue::SetSP(ValueImplSP impl_sp) { m_opaque_sp = impl_sp; } |
1059 | |
1060 | void SBValue::SetSP(const lldb::ValueObjectSP &sp) { |
1061 | if (sp) { |
1062 | lldb::TargetSP target_sp(sp->GetTargetSP()); |
1063 | if (target_sp) { |
1064 | lldb::DynamicValueType use_dynamic = target_sp->GetPreferDynamicValue(); |
1065 | bool use_synthetic = |
1066 | target_sp->TargetProperties::GetEnableSyntheticValue(); |
1067 | m_opaque_sp = ValueImplSP(new ValueImpl(sp, use_dynamic, use_synthetic)); |
1068 | } else |
1069 | m_opaque_sp = ValueImplSP(new ValueImpl(sp, eNoDynamicValues, true)); |
1070 | } else |
1071 | m_opaque_sp = ValueImplSP(new ValueImpl(sp, eNoDynamicValues, false)); |
1072 | } |
1073 | |
1074 | void SBValue::SetSP(const lldb::ValueObjectSP &sp, |
1075 | lldb::DynamicValueType use_dynamic) { |
1076 | if (sp) { |
1077 | lldb::TargetSP target_sp(sp->GetTargetSP()); |
1078 | if (target_sp) { |
1079 | bool use_synthetic = |
1080 | target_sp->TargetProperties::GetEnableSyntheticValue(); |
1081 | SetSP(sp, use_dynamic, use_synthetic); |
1082 | } else |
1083 | SetSP(sp, use_dynamic, use_synthetic: true); |
1084 | } else |
1085 | SetSP(sp, use_dynamic, use_synthetic: false); |
1086 | } |
1087 | |
1088 | void SBValue::SetSP(const lldb::ValueObjectSP &sp, bool use_synthetic) { |
1089 | if (sp) { |
1090 | lldb::TargetSP target_sp(sp->GetTargetSP()); |
1091 | if (target_sp) { |
1092 | lldb::DynamicValueType use_dynamic = target_sp->GetPreferDynamicValue(); |
1093 | SetSP(sp, use_dynamic, use_synthetic); |
1094 | } else |
1095 | SetSP(sp, use_dynamic: eNoDynamicValues, use_synthetic); |
1096 | } else |
1097 | SetSP(sp, use_dynamic: eNoDynamicValues, use_synthetic); |
1098 | } |
1099 | |
1100 | void SBValue::SetSP(const lldb::ValueObjectSP &sp, |
1101 | lldb::DynamicValueType use_dynamic, bool use_synthetic) { |
1102 | m_opaque_sp = ValueImplSP(new ValueImpl(sp, use_dynamic, use_synthetic)); |
1103 | } |
1104 | |
1105 | void SBValue::SetSP(const lldb::ValueObjectSP &sp, |
1106 | lldb::DynamicValueType use_dynamic, bool use_synthetic, |
1107 | const char *name) { |
1108 | m_opaque_sp = |
1109 | ValueImplSP(new ValueImpl(sp, use_dynamic, use_synthetic, name)); |
1110 | } |
1111 | |
1112 | bool SBValue::GetExpressionPath(SBStream &description) { |
1113 | LLDB_INSTRUMENT_VA(this, description); |
1114 | |
1115 | ValueLocker locker; |
1116 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1117 | if (value_sp) { |
1118 | value_sp->GetExpressionPath(s&: description.ref()); |
1119 | return true; |
1120 | } |
1121 | return false; |
1122 | } |
1123 | |
1124 | bool SBValue::GetExpressionPath(SBStream &description, |
1125 | bool qualify_cxx_base_classes) { |
1126 | LLDB_INSTRUMENT_VA(this, description, qualify_cxx_base_classes); |
1127 | |
1128 | ValueLocker locker; |
1129 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1130 | if (value_sp) { |
1131 | value_sp->GetExpressionPath(s&: description.ref()); |
1132 | return true; |
1133 | } |
1134 | return false; |
1135 | } |
1136 | |
1137 | lldb::SBValue SBValue::EvaluateExpression(const char *expr) const { |
1138 | LLDB_INSTRUMENT_VA(this, expr); |
1139 | |
1140 | ValueLocker locker; |
1141 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1142 | if (!value_sp) |
1143 | return SBValue(); |
1144 | |
1145 | lldb::TargetSP target_sp = value_sp->GetTargetSP(); |
1146 | if (!target_sp) |
1147 | return SBValue(); |
1148 | |
1149 | lldb::SBExpressionOptions options; |
1150 | options.SetFetchDynamicValue(target_sp->GetPreferDynamicValue()); |
1151 | options.SetUnwindOnError(true); |
1152 | options.SetIgnoreBreakpoints(true); |
1153 | |
1154 | return EvaluateExpression(expr, options, name: nullptr); |
1155 | } |
1156 | |
1157 | lldb::SBValue |
1158 | SBValue::EvaluateExpression(const char *expr, |
1159 | const SBExpressionOptions &options) const { |
1160 | LLDB_INSTRUMENT_VA(this, expr, options); |
1161 | |
1162 | return EvaluateExpression(expr, options, name: nullptr); |
1163 | } |
1164 | |
1165 | lldb::SBValue SBValue::EvaluateExpression(const char *expr, |
1166 | const SBExpressionOptions &options, |
1167 | const char *name) const { |
1168 | LLDB_INSTRUMENT_VA(this, expr, options, name); |
1169 | |
1170 | if (!expr || expr[0] == '\0') { |
1171 | return SBValue(); |
1172 | } |
1173 | |
1174 | |
1175 | ValueLocker locker; |
1176 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1177 | if (!value_sp) { |
1178 | return SBValue(); |
1179 | } |
1180 | |
1181 | lldb::TargetSP target_sp = value_sp->GetTargetSP(); |
1182 | if (!target_sp) { |
1183 | return SBValue(); |
1184 | } |
1185 | |
1186 | std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex()); |
1187 | ExecutionContext exe_ctx(target_sp.get()); |
1188 | |
1189 | StackFrame *frame = exe_ctx.GetFramePtr(); |
1190 | if (!frame) { |
1191 | return SBValue(); |
1192 | } |
1193 | |
1194 | ValueObjectSP res_val_sp; |
1195 | target_sp->EvaluateExpression(expression: expr, exe_scope: frame, result_valobj_sp&: res_val_sp, options: options.ref(), fixed_expression: nullptr, |
1196 | ctx_obj: value_sp.get()); |
1197 | |
1198 | if (name) |
1199 | res_val_sp->SetName(ConstString(name)); |
1200 | |
1201 | SBValue result; |
1202 | result.SetSP(sp: res_val_sp, use_dynamic: options.GetFetchDynamicValue()); |
1203 | return result; |
1204 | } |
1205 | |
1206 | bool SBValue::GetDescription(SBStream &description) { |
1207 | LLDB_INSTRUMENT_VA(this, description); |
1208 | |
1209 | Stream &strm = description.ref(); |
1210 | |
1211 | ValueLocker locker; |
1212 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1213 | if (value_sp) { |
1214 | DumpValueObjectOptions options; |
1215 | options.SetUseDynamicType(m_opaque_sp->GetUseDynamic()); |
1216 | options.SetUseSyntheticValue(m_opaque_sp->GetUseSynthetic()); |
1217 | value_sp->Dump(s&: strm, options); |
1218 | } else { |
1219 | strm.PutCString(cstr: "No value" ); |
1220 | } |
1221 | |
1222 | return true; |
1223 | } |
1224 | |
1225 | lldb::Format SBValue::GetFormat() { |
1226 | LLDB_INSTRUMENT_VA(this); |
1227 | |
1228 | ValueLocker locker; |
1229 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1230 | if (value_sp) |
1231 | return value_sp->GetFormat(); |
1232 | return eFormatDefault; |
1233 | } |
1234 | |
1235 | void SBValue::SetFormat(lldb::Format format) { |
1236 | LLDB_INSTRUMENT_VA(this, format); |
1237 | |
1238 | ValueLocker locker; |
1239 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1240 | if (value_sp) |
1241 | value_sp->SetFormat(format); |
1242 | } |
1243 | |
1244 | lldb::SBValue SBValue::AddressOf() { |
1245 | LLDB_INSTRUMENT_VA(this); |
1246 | |
1247 | SBValue sb_value; |
1248 | ValueLocker locker; |
1249 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1250 | if (value_sp) { |
1251 | Status error; |
1252 | sb_value.SetSP(sp: value_sp->AddressOf(error), use_dynamic: GetPreferDynamicValue(), |
1253 | use_synthetic: GetPreferSyntheticValue()); |
1254 | } |
1255 | |
1256 | return sb_value; |
1257 | } |
1258 | |
1259 | lldb::addr_t SBValue::GetLoadAddress() { |
1260 | LLDB_INSTRUMENT_VA(this); |
1261 | |
1262 | lldb::addr_t value = LLDB_INVALID_ADDRESS; |
1263 | ValueLocker locker; |
1264 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1265 | if (value_sp) { |
1266 | TargetSP target_sp(value_sp->GetTargetSP()); |
1267 | if (target_sp) { |
1268 | const bool scalar_is_load_address = true; |
1269 | AddressType addr_type; |
1270 | value = value_sp->GetAddressOf(scalar_is_load_address, address_type: &addr_type); |
1271 | if (addr_type == eAddressTypeFile) { |
1272 | ModuleSP module_sp(value_sp->GetModule()); |
1273 | if (!module_sp) |
1274 | value = LLDB_INVALID_ADDRESS; |
1275 | else { |
1276 | Address addr; |
1277 | module_sp->ResolveFileAddress(vm_addr: value, so_addr&: addr); |
1278 | value = addr.GetLoadAddress(target: target_sp.get()); |
1279 | } |
1280 | } else if (addr_type == eAddressTypeHost || |
1281 | addr_type == eAddressTypeInvalid) |
1282 | value = LLDB_INVALID_ADDRESS; |
1283 | } |
1284 | } |
1285 | |
1286 | return value; |
1287 | } |
1288 | |
1289 | lldb::SBAddress SBValue::GetAddress() { |
1290 | LLDB_INSTRUMENT_VA(this); |
1291 | |
1292 | Address addr; |
1293 | ValueLocker locker; |
1294 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1295 | if (value_sp) { |
1296 | TargetSP target_sp(value_sp->GetTargetSP()); |
1297 | if (target_sp) { |
1298 | lldb::addr_t value = LLDB_INVALID_ADDRESS; |
1299 | const bool scalar_is_load_address = true; |
1300 | AddressType addr_type; |
1301 | value = value_sp->GetAddressOf(scalar_is_load_address, address_type: &addr_type); |
1302 | if (addr_type == eAddressTypeFile) { |
1303 | ModuleSP module_sp(value_sp->GetModule()); |
1304 | if (module_sp) |
1305 | module_sp->ResolveFileAddress(vm_addr: value, so_addr&: addr); |
1306 | } else if (addr_type == eAddressTypeLoad) { |
1307 | // no need to check the return value on this.. if it can actually do |
1308 | // the resolve addr will be in the form (section,offset), otherwise it |
1309 | // will simply be returned as (NULL, value) |
1310 | addr.SetLoadAddress(load_addr: value, target: target_sp.get()); |
1311 | } |
1312 | } |
1313 | } |
1314 | |
1315 | return SBAddress(addr); |
1316 | } |
1317 | |
1318 | lldb::SBData SBValue::GetPointeeData(uint32_t item_idx, uint32_t item_count) { |
1319 | LLDB_INSTRUMENT_VA(this, item_idx, item_count); |
1320 | |
1321 | lldb::SBData sb_data; |
1322 | ValueLocker locker; |
1323 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1324 | if (value_sp) { |
1325 | TargetSP target_sp(value_sp->GetTargetSP()); |
1326 | if (target_sp) { |
1327 | DataExtractorSP data_sp(new DataExtractor()); |
1328 | value_sp->GetPointeeData(data&: *data_sp, item_idx, item_count); |
1329 | if (data_sp->GetByteSize() > 0) |
1330 | *sb_data = data_sp; |
1331 | } |
1332 | } |
1333 | |
1334 | return sb_data; |
1335 | } |
1336 | |
1337 | lldb::SBData SBValue::GetData() { |
1338 | LLDB_INSTRUMENT_VA(this); |
1339 | |
1340 | lldb::SBData sb_data; |
1341 | ValueLocker locker; |
1342 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1343 | if (value_sp) { |
1344 | DataExtractorSP data_sp(new DataExtractor()); |
1345 | Status error; |
1346 | value_sp->GetData(data&: *data_sp, error); |
1347 | if (error.Success()) |
1348 | *sb_data = data_sp; |
1349 | } |
1350 | |
1351 | return sb_data; |
1352 | } |
1353 | |
1354 | bool SBValue::SetData(lldb::SBData &data, SBError &error) { |
1355 | LLDB_INSTRUMENT_VA(this, data, error); |
1356 | |
1357 | ValueLocker locker; |
1358 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1359 | bool ret = true; |
1360 | |
1361 | if (value_sp) { |
1362 | DataExtractor * = data.get(); |
1363 | |
1364 | if (!data_extractor) { |
1365 | error.SetErrorString("No data to set" ); |
1366 | ret = false; |
1367 | } else { |
1368 | Status set_error; |
1369 | |
1370 | value_sp->SetData(data&: *data_extractor, error&: set_error); |
1371 | |
1372 | if (!set_error.Success()) { |
1373 | error.SetErrorStringWithFormat("Couldn't set data: %s" , |
1374 | set_error.AsCString()); |
1375 | ret = false; |
1376 | } |
1377 | } |
1378 | } else { |
1379 | error.SetErrorStringWithFormat( |
1380 | "Couldn't set data: could not get SBValue: %s" , |
1381 | locker.GetError().AsCString()); |
1382 | ret = false; |
1383 | } |
1384 | |
1385 | return ret; |
1386 | } |
1387 | |
1388 | lldb::SBValue SBValue::Clone(const char *new_name) { |
1389 | LLDB_INSTRUMENT_VA(this, new_name); |
1390 | |
1391 | ValueLocker locker; |
1392 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1393 | |
1394 | if (value_sp) |
1395 | return lldb::SBValue(value_sp->Clone(new_name: ConstString(new_name))); |
1396 | else |
1397 | return lldb::SBValue(); |
1398 | } |
1399 | |
1400 | lldb::SBDeclaration SBValue::GetDeclaration() { |
1401 | LLDB_INSTRUMENT_VA(this); |
1402 | |
1403 | ValueLocker locker; |
1404 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1405 | SBDeclaration decl_sb; |
1406 | if (value_sp) { |
1407 | Declaration decl; |
1408 | if (value_sp->GetDeclaration(decl)) |
1409 | decl_sb.SetDeclaration(decl); |
1410 | } |
1411 | return decl_sb; |
1412 | } |
1413 | |
1414 | lldb::SBWatchpoint SBValue::Watch(bool resolve_location, bool read, bool write, |
1415 | SBError &error) { |
1416 | LLDB_INSTRUMENT_VA(this, resolve_location, read, write, error); |
1417 | |
1418 | SBWatchpoint sb_watchpoint; |
1419 | |
1420 | // If the SBValue is not valid, there's no point in even trying to watch it. |
1421 | ValueLocker locker; |
1422 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1423 | TargetSP target_sp(GetTarget().GetSP()); |
1424 | if (value_sp && target_sp) { |
1425 | // Read and Write cannot both be false. |
1426 | if (!read && !write) |
1427 | return sb_watchpoint; |
1428 | |
1429 | // If the value is not in scope, don't try and watch and invalid value |
1430 | if (!IsInScope()) |
1431 | return sb_watchpoint; |
1432 | |
1433 | addr_t addr = GetLoadAddress(); |
1434 | if (addr == LLDB_INVALID_ADDRESS) |
1435 | return sb_watchpoint; |
1436 | size_t byte_size = GetByteSize(); |
1437 | if (byte_size == 0) |
1438 | return sb_watchpoint; |
1439 | |
1440 | uint32_t watch_type = 0; |
1441 | if (read) { |
1442 | watch_type |= LLDB_WATCH_TYPE_READ; |
1443 | // read + write, the most likely intention |
1444 | // is to catch all writes to this, not just |
1445 | // value modifications. |
1446 | if (write) |
1447 | watch_type |= LLDB_WATCH_TYPE_WRITE; |
1448 | } else { |
1449 | if (write) |
1450 | watch_type |= LLDB_WATCH_TYPE_MODIFY; |
1451 | } |
1452 | |
1453 | Status rc; |
1454 | CompilerType type(value_sp->GetCompilerType()); |
1455 | WatchpointSP watchpoint_sp = |
1456 | target_sp->CreateWatchpoint(addr, size: byte_size, type: &type, kind: watch_type, error&: rc); |
1457 | error.SetError(rc); |
1458 | |
1459 | if (watchpoint_sp) { |
1460 | sb_watchpoint.SetSP(watchpoint_sp); |
1461 | Declaration decl; |
1462 | if (value_sp->GetDeclaration(decl)) { |
1463 | if (decl.GetFile()) { |
1464 | StreamString ss; |
1465 | // True to show fullpath for declaration file. |
1466 | decl.DumpStopContext(s: &ss, show_fullpaths: true); |
1467 | watchpoint_sp->SetDeclInfo(std::string(ss.GetString())); |
1468 | } |
1469 | } |
1470 | } |
1471 | } else if (target_sp) { |
1472 | error.SetErrorStringWithFormat("could not get SBValue: %s" , |
1473 | locker.GetError().AsCString()); |
1474 | } else { |
1475 | error.SetErrorString("could not set watchpoint, a target is required" ); |
1476 | } |
1477 | |
1478 | return sb_watchpoint; |
1479 | } |
1480 | |
1481 | // FIXME: Remove this method impl (as well as the decl in .h) once it is no |
1482 | // longer needed. |
1483 | // Backward compatibility fix in the interim. |
1484 | lldb::SBWatchpoint SBValue::Watch(bool resolve_location, bool read, |
1485 | bool write) { |
1486 | LLDB_INSTRUMENT_VA(this, resolve_location, read, write); |
1487 | |
1488 | SBError error; |
1489 | return Watch(resolve_location, read, write, error); |
1490 | } |
1491 | |
1492 | lldb::SBWatchpoint SBValue::WatchPointee(bool resolve_location, bool read, |
1493 | bool write, SBError &error) { |
1494 | LLDB_INSTRUMENT_VA(this, resolve_location, read, write, error); |
1495 | |
1496 | SBWatchpoint sb_watchpoint; |
1497 | if (IsInScope() && GetType().IsPointerType()) |
1498 | sb_watchpoint = Dereference().Watch(resolve_location, read, write, error); |
1499 | return sb_watchpoint; |
1500 | } |
1501 | |
1502 | lldb::SBValue SBValue::Persist() { |
1503 | LLDB_INSTRUMENT_VA(this); |
1504 | |
1505 | ValueLocker locker; |
1506 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1507 | SBValue persisted_sb; |
1508 | if (value_sp) { |
1509 | persisted_sb.SetSP(value_sp->Persist()); |
1510 | } |
1511 | return persisted_sb; |
1512 | } |
1513 | |
1514 | lldb::SBValue SBValue::GetVTable() { |
1515 | SBValue vtable_sb; |
1516 | ValueLocker locker; |
1517 | lldb::ValueObjectSP value_sp(GetSP(locker)); |
1518 | if (!value_sp) |
1519 | return vtable_sb; |
1520 | |
1521 | vtable_sb.SetSP(value_sp->GetVTable()); |
1522 | return vtable_sb; |
1523 | } |
1524 | |