1 | //===-- SBFrame.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 <algorithm> |
10 | #include <set> |
11 | #include <string> |
12 | |
13 | #include "lldb/API/SBFrame.h" |
14 | |
15 | #include "lldb/lldb-types.h" |
16 | |
17 | #include "Utils.h" |
18 | #include "lldb/Core/Address.h" |
19 | #include "lldb/Core/Debugger.h" |
20 | #include "lldb/Expression/ExpressionVariable.h" |
21 | #include "lldb/Expression/UserExpression.h" |
22 | #include "lldb/Host/Host.h" |
23 | #include "lldb/Symbol/Block.h" |
24 | #include "lldb/Symbol/Function.h" |
25 | #include "lldb/Symbol/Symbol.h" |
26 | #include "lldb/Symbol/SymbolContext.h" |
27 | #include "lldb/Symbol/Variable.h" |
28 | #include "lldb/Symbol/VariableList.h" |
29 | #include "lldb/Target/ExecutionContext.h" |
30 | #include "lldb/Target/Process.h" |
31 | #include "lldb/Target/RegisterContext.h" |
32 | #include "lldb/Target/StackFrame.h" |
33 | #include "lldb/Target/StackFrameRecognizer.h" |
34 | #include "lldb/Target/StackID.h" |
35 | #include "lldb/Target/Target.h" |
36 | #include "lldb/Target/Thread.h" |
37 | #include "lldb/Utility/ConstString.h" |
38 | #include "lldb/Utility/Instrumentation.h" |
39 | #include "lldb/Utility/LLDBLog.h" |
40 | #include "lldb/Utility/Stream.h" |
41 | #include "lldb/ValueObject/ValueObjectConstResult.h" |
42 | #include "lldb/ValueObject/ValueObjectRegister.h" |
43 | #include "lldb/ValueObject/ValueObjectVariable.h" |
44 | |
45 | #include "lldb/API/SBAddress.h" |
46 | #include "lldb/API/SBDebugger.h" |
47 | #include "lldb/API/SBExpressionOptions.h" |
48 | #include "lldb/API/SBFormat.h" |
49 | #include "lldb/API/SBStream.h" |
50 | #include "lldb/API/SBStructuredData.h" |
51 | #include "lldb/API/SBSymbolContext.h" |
52 | #include "lldb/API/SBThread.h" |
53 | #include "lldb/API/SBValue.h" |
54 | #include "lldb/API/SBVariablesOptions.h" |
55 | |
56 | #include "llvm/Support/PrettyStackTrace.h" |
57 | |
58 | using namespace lldb; |
59 | using namespace lldb_private; |
60 | |
61 | SBFrame::SBFrame() : m_opaque_sp(new ExecutionContextRef()) { |
62 | LLDB_INSTRUMENT_VA(this); |
63 | } |
64 | |
65 | SBFrame::SBFrame(const StackFrameSP &lldb_object_sp) |
66 | : m_opaque_sp(new ExecutionContextRef(lldb_object_sp)) { |
67 | LLDB_INSTRUMENT_VA(this, lldb_object_sp); |
68 | } |
69 | |
70 | SBFrame::SBFrame(const SBFrame &rhs) { |
71 | LLDB_INSTRUMENT_VA(this, rhs); |
72 | |
73 | m_opaque_sp = clone(src: rhs.m_opaque_sp); |
74 | } |
75 | |
76 | SBFrame::~SBFrame() = default; |
77 | |
78 | const SBFrame &SBFrame::operator=(const SBFrame &rhs) { |
79 | LLDB_INSTRUMENT_VA(this, rhs); |
80 | |
81 | if (this != &rhs) |
82 | m_opaque_sp = clone(src: rhs.m_opaque_sp); |
83 | return *this; |
84 | } |
85 | |
86 | StackFrameSP SBFrame::GetFrameSP() const { |
87 | return (m_opaque_sp ? m_opaque_sp->GetFrameSP() : StackFrameSP()); |
88 | } |
89 | |
90 | void SBFrame::SetFrameSP(const StackFrameSP &lldb_object_sp) { |
91 | return m_opaque_sp->SetFrameSP(lldb_object_sp); |
92 | } |
93 | |
94 | bool SBFrame::IsValid() const { |
95 | LLDB_INSTRUMENT_VA(this); |
96 | return this->operator bool(); |
97 | } |
98 | SBFrame::operator bool() const { |
99 | LLDB_INSTRUMENT_VA(this); |
100 | |
101 | std::unique_lock<std::recursive_mutex> lock; |
102 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
103 | |
104 | Target *target = exe_ctx.GetTargetPtr(); |
105 | Process *process = exe_ctx.GetProcessPtr(); |
106 | if (target && process) { |
107 | Process::StopLocker stop_locker; |
108 | if (stop_locker.TryLock(lock: &process->GetRunLock())) |
109 | return GetFrameSP().get() != nullptr; |
110 | } |
111 | |
112 | // Without a target & process we can't have a valid stack frame. |
113 | return false; |
114 | } |
115 | |
116 | SBSymbolContext SBFrame::GetSymbolContext(uint32_t resolve_scope) const { |
117 | LLDB_INSTRUMENT_VA(this, resolve_scope); |
118 | |
119 | SBSymbolContext sb_sym_ctx; |
120 | std::unique_lock<std::recursive_mutex> lock; |
121 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
122 | SymbolContextItem scope = static_cast<SymbolContextItem>(resolve_scope); |
123 | Target *target = exe_ctx.GetTargetPtr(); |
124 | Process *process = exe_ctx.GetProcessPtr(); |
125 | if (target && process) { |
126 | Process::StopLocker stop_locker; |
127 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
128 | if (StackFrame *frame = exe_ctx.GetFramePtr()) |
129 | sb_sym_ctx = frame->GetSymbolContext(resolve_scope: scope); |
130 | } |
131 | } |
132 | |
133 | return sb_sym_ctx; |
134 | } |
135 | |
136 | SBModule SBFrame::GetModule() const { |
137 | LLDB_INSTRUMENT_VA(this); |
138 | |
139 | SBModule sb_module; |
140 | ModuleSP module_sp; |
141 | std::unique_lock<std::recursive_mutex> lock; |
142 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
143 | |
144 | StackFrame *frame = nullptr; |
145 | Target *target = exe_ctx.GetTargetPtr(); |
146 | Process *process = exe_ctx.GetProcessPtr(); |
147 | if (target && process) { |
148 | Process::StopLocker stop_locker; |
149 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
150 | frame = exe_ctx.GetFramePtr(); |
151 | if (frame) { |
152 | module_sp = frame->GetSymbolContext(resolve_scope: eSymbolContextModule).module_sp; |
153 | sb_module.SetSP(module_sp); |
154 | } |
155 | } |
156 | } |
157 | |
158 | return sb_module; |
159 | } |
160 | |
161 | SBCompileUnit SBFrame::GetCompileUnit() const { |
162 | LLDB_INSTRUMENT_VA(this); |
163 | |
164 | SBCompileUnit sb_comp_unit; |
165 | std::unique_lock<std::recursive_mutex> lock; |
166 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
167 | |
168 | StackFrame *frame = nullptr; |
169 | Target *target = exe_ctx.GetTargetPtr(); |
170 | Process *process = exe_ctx.GetProcessPtr(); |
171 | if (target && process) { |
172 | Process::StopLocker stop_locker; |
173 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
174 | frame = exe_ctx.GetFramePtr(); |
175 | if (frame) { |
176 | sb_comp_unit.reset( |
177 | lldb_object_ptr: frame->GetSymbolContext(resolve_scope: eSymbolContextCompUnit).comp_unit); |
178 | } |
179 | } |
180 | } |
181 | |
182 | return sb_comp_unit; |
183 | } |
184 | |
185 | SBFunction SBFrame::GetFunction() const { |
186 | LLDB_INSTRUMENT_VA(this); |
187 | |
188 | SBFunction sb_function; |
189 | std::unique_lock<std::recursive_mutex> lock; |
190 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
191 | |
192 | StackFrame *frame = nullptr; |
193 | Target *target = exe_ctx.GetTargetPtr(); |
194 | Process *process = exe_ctx.GetProcessPtr(); |
195 | if (target && process) { |
196 | Process::StopLocker stop_locker; |
197 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
198 | frame = exe_ctx.GetFramePtr(); |
199 | if (frame) { |
200 | sb_function.reset( |
201 | lldb_object_ptr: frame->GetSymbolContext(resolve_scope: eSymbolContextFunction).function); |
202 | } |
203 | } |
204 | } |
205 | |
206 | return sb_function; |
207 | } |
208 | |
209 | SBSymbol SBFrame::GetSymbol() const { |
210 | LLDB_INSTRUMENT_VA(this); |
211 | |
212 | SBSymbol sb_symbol; |
213 | std::unique_lock<std::recursive_mutex> lock; |
214 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
215 | |
216 | StackFrame *frame = nullptr; |
217 | Target *target = exe_ctx.GetTargetPtr(); |
218 | Process *process = exe_ctx.GetProcessPtr(); |
219 | if (target && process) { |
220 | Process::StopLocker stop_locker; |
221 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
222 | frame = exe_ctx.GetFramePtr(); |
223 | if (frame) { |
224 | sb_symbol.reset(frame->GetSymbolContext(resolve_scope: eSymbolContextSymbol).symbol); |
225 | } |
226 | } |
227 | } |
228 | |
229 | return sb_symbol; |
230 | } |
231 | |
232 | SBBlock SBFrame::GetBlock() const { |
233 | LLDB_INSTRUMENT_VA(this); |
234 | |
235 | SBBlock sb_block; |
236 | std::unique_lock<std::recursive_mutex> lock; |
237 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
238 | |
239 | StackFrame *frame = nullptr; |
240 | Target *target = exe_ctx.GetTargetPtr(); |
241 | Process *process = exe_ctx.GetProcessPtr(); |
242 | if (target && process) { |
243 | Process::StopLocker stop_locker; |
244 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
245 | frame = exe_ctx.GetFramePtr(); |
246 | if (frame) |
247 | sb_block.SetPtr(frame->GetSymbolContext(resolve_scope: eSymbolContextBlock).block); |
248 | } |
249 | } |
250 | return sb_block; |
251 | } |
252 | |
253 | SBBlock SBFrame::GetFrameBlock() const { |
254 | LLDB_INSTRUMENT_VA(this); |
255 | |
256 | SBBlock sb_block; |
257 | std::unique_lock<std::recursive_mutex> lock; |
258 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
259 | |
260 | StackFrame *frame = nullptr; |
261 | Target *target = exe_ctx.GetTargetPtr(); |
262 | Process *process = exe_ctx.GetProcessPtr(); |
263 | if (target && process) { |
264 | Process::StopLocker stop_locker; |
265 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
266 | frame = exe_ctx.GetFramePtr(); |
267 | if (frame) |
268 | sb_block.SetPtr(frame->GetFrameBlock()); |
269 | } |
270 | } |
271 | return sb_block; |
272 | } |
273 | |
274 | SBLineEntry SBFrame::GetLineEntry() const { |
275 | LLDB_INSTRUMENT_VA(this); |
276 | |
277 | SBLineEntry sb_line_entry; |
278 | std::unique_lock<std::recursive_mutex> lock; |
279 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
280 | |
281 | StackFrame *frame = nullptr; |
282 | Target *target = exe_ctx.GetTargetPtr(); |
283 | Process *process = exe_ctx.GetProcessPtr(); |
284 | if (target && process) { |
285 | Process::StopLocker stop_locker; |
286 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
287 | frame = exe_ctx.GetFramePtr(); |
288 | if (frame) { |
289 | sb_line_entry.SetLineEntry( |
290 | frame->GetSymbolContext(resolve_scope: eSymbolContextLineEntry).line_entry); |
291 | } |
292 | } |
293 | } |
294 | return sb_line_entry; |
295 | } |
296 | |
297 | uint32_t SBFrame::GetFrameID() const { |
298 | LLDB_INSTRUMENT_VA(this); |
299 | |
300 | uint32_t frame_idx = UINT32_MAX; |
301 | |
302 | std::unique_lock<std::recursive_mutex> lock; |
303 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
304 | |
305 | StackFrame *frame = exe_ctx.GetFramePtr(); |
306 | if (frame) |
307 | frame_idx = frame->GetFrameIndex(); |
308 | |
309 | return frame_idx; |
310 | } |
311 | |
312 | lldb::addr_t SBFrame::GetCFA() const { |
313 | LLDB_INSTRUMENT_VA(this); |
314 | |
315 | std::unique_lock<std::recursive_mutex> lock; |
316 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
317 | |
318 | StackFrame *frame = exe_ctx.GetFramePtr(); |
319 | if (frame) |
320 | return frame->GetStackID().GetCallFrameAddress(); |
321 | return LLDB_INVALID_ADDRESS; |
322 | } |
323 | |
324 | addr_t SBFrame::GetPC() const { |
325 | LLDB_INSTRUMENT_VA(this); |
326 | |
327 | addr_t addr = LLDB_INVALID_ADDRESS; |
328 | std::unique_lock<std::recursive_mutex> lock; |
329 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
330 | |
331 | StackFrame *frame = nullptr; |
332 | Target *target = exe_ctx.GetTargetPtr(); |
333 | Process *process = exe_ctx.GetProcessPtr(); |
334 | if (target && process) { |
335 | Process::StopLocker stop_locker; |
336 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
337 | frame = exe_ctx.GetFramePtr(); |
338 | if (frame) { |
339 | addr = frame->GetFrameCodeAddress().GetOpcodeLoadAddress( |
340 | target, addr_class: AddressClass::eCode); |
341 | } |
342 | } |
343 | } |
344 | |
345 | return addr; |
346 | } |
347 | |
348 | bool SBFrame::SetPC(addr_t new_pc) { |
349 | LLDB_INSTRUMENT_VA(this, new_pc); |
350 | |
351 | bool ret_val = false; |
352 | std::unique_lock<std::recursive_mutex> lock; |
353 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
354 | |
355 | Target *target = exe_ctx.GetTargetPtr(); |
356 | Process *process = exe_ctx.GetProcessPtr(); |
357 | if (target && process) { |
358 | Process::StopLocker stop_locker; |
359 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
360 | if (StackFrame *frame = exe_ctx.GetFramePtr()) { |
361 | if (RegisterContextSP reg_ctx_sp = frame->GetRegisterContext()) { |
362 | ret_val = reg_ctx_sp->SetPC(new_pc); |
363 | } |
364 | } |
365 | } |
366 | } |
367 | |
368 | return ret_val; |
369 | } |
370 | |
371 | addr_t SBFrame::GetSP() const { |
372 | LLDB_INSTRUMENT_VA(this); |
373 | |
374 | addr_t addr = LLDB_INVALID_ADDRESS; |
375 | std::unique_lock<std::recursive_mutex> lock; |
376 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
377 | |
378 | Target *target = exe_ctx.GetTargetPtr(); |
379 | Process *process = exe_ctx.GetProcessPtr(); |
380 | if (target && process) { |
381 | Process::StopLocker stop_locker; |
382 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
383 | if (StackFrame *frame = exe_ctx.GetFramePtr()) { |
384 | if (RegisterContextSP reg_ctx_sp = frame->GetRegisterContext()) { |
385 | addr = reg_ctx_sp->GetSP(); |
386 | } |
387 | } |
388 | } |
389 | } |
390 | |
391 | return addr; |
392 | } |
393 | |
394 | addr_t SBFrame::GetFP() const { |
395 | LLDB_INSTRUMENT_VA(this); |
396 | |
397 | addr_t addr = LLDB_INVALID_ADDRESS; |
398 | std::unique_lock<std::recursive_mutex> lock; |
399 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
400 | |
401 | Target *target = exe_ctx.GetTargetPtr(); |
402 | Process *process = exe_ctx.GetProcessPtr(); |
403 | if (target && process) { |
404 | Process::StopLocker stop_locker; |
405 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
406 | if (StackFrame *frame = exe_ctx.GetFramePtr()) { |
407 | if (RegisterContextSP reg_ctx_sp = frame->GetRegisterContext()) { |
408 | addr = reg_ctx_sp->GetFP(); |
409 | } |
410 | } |
411 | } |
412 | } |
413 | |
414 | return addr; |
415 | } |
416 | |
417 | SBAddress SBFrame::GetPCAddress() const { |
418 | LLDB_INSTRUMENT_VA(this); |
419 | |
420 | SBAddress sb_addr; |
421 | std::unique_lock<std::recursive_mutex> lock; |
422 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
423 | |
424 | StackFrame *frame = exe_ctx.GetFramePtr(); |
425 | Target *target = exe_ctx.GetTargetPtr(); |
426 | Process *process = exe_ctx.GetProcessPtr(); |
427 | if (target && process) { |
428 | Process::StopLocker stop_locker; |
429 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
430 | frame = exe_ctx.GetFramePtr(); |
431 | if (frame) |
432 | sb_addr.SetAddress(frame->GetFrameCodeAddress()); |
433 | } |
434 | } |
435 | return sb_addr; |
436 | } |
437 | |
438 | void SBFrame::Clear() { |
439 | LLDB_INSTRUMENT_VA(this); |
440 | |
441 | m_opaque_sp->Clear(); |
442 | } |
443 | |
444 | lldb::SBValue SBFrame::GetValueForVariablePath(const char *var_path) { |
445 | LLDB_INSTRUMENT_VA(this, var_path); |
446 | |
447 | SBValue sb_value; |
448 | std::unique_lock<std::recursive_mutex> lock; |
449 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
450 | |
451 | StackFrame *frame = exe_ctx.GetFramePtr(); |
452 | Target *target = exe_ctx.GetTargetPtr(); |
453 | if (frame && target) { |
454 | lldb::DynamicValueType use_dynamic = |
455 | frame->CalculateTarget()->GetPreferDynamicValue(); |
456 | sb_value = GetValueForVariablePath(var_expr_cstr: var_path, use_dynamic); |
457 | } |
458 | return sb_value; |
459 | } |
460 | |
461 | lldb::SBValue SBFrame::GetValueForVariablePath(const char *var_path, |
462 | DynamicValueType use_dynamic) { |
463 | LLDB_INSTRUMENT_VA(this, var_path, use_dynamic); |
464 | |
465 | SBValue sb_value; |
466 | if (var_path == nullptr || var_path[0] == '\0') { |
467 | return sb_value; |
468 | } |
469 | |
470 | std::unique_lock<std::recursive_mutex> lock; |
471 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
472 | |
473 | StackFrame *frame = nullptr; |
474 | Target *target = exe_ctx.GetTargetPtr(); |
475 | Process *process = exe_ctx.GetProcessPtr(); |
476 | if (target && process) { |
477 | Process::StopLocker stop_locker; |
478 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
479 | frame = exe_ctx.GetFramePtr(); |
480 | if (frame) { |
481 | VariableSP var_sp; |
482 | Status error; |
483 | ValueObjectSP value_sp(frame->GetValueForVariableExpressionPath( |
484 | var_expr: var_path, use_dynamic: eNoDynamicValues, |
485 | options: StackFrame::eExpressionPathOptionCheckPtrVsMember | |
486 | StackFrame::eExpressionPathOptionsAllowDirectIVarAccess, |
487 | var_sp, error)); |
488 | sb_value.SetSP(sp: value_sp, use_dynamic); |
489 | } |
490 | } |
491 | } |
492 | return sb_value; |
493 | } |
494 | |
495 | SBValue SBFrame::FindVariable(const char *name) { |
496 | LLDB_INSTRUMENT_VA(this, name); |
497 | |
498 | SBValue value; |
499 | std::unique_lock<std::recursive_mutex> lock; |
500 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
501 | |
502 | StackFrame *frame = exe_ctx.GetFramePtr(); |
503 | Target *target = exe_ctx.GetTargetPtr(); |
504 | if (frame && target) { |
505 | lldb::DynamicValueType use_dynamic = |
506 | frame->CalculateTarget()->GetPreferDynamicValue(); |
507 | value = FindVariable(var_name: name, use_dynamic); |
508 | } |
509 | return value; |
510 | } |
511 | |
512 | SBValue SBFrame::FindVariable(const char *name, |
513 | lldb::DynamicValueType use_dynamic) { |
514 | LLDB_INSTRUMENT_VA(this, name, use_dynamic); |
515 | |
516 | VariableSP var_sp; |
517 | SBValue sb_value; |
518 | |
519 | if (name == nullptr || name[0] == '\0') { |
520 | return sb_value; |
521 | } |
522 | |
523 | ValueObjectSP value_sp; |
524 | std::unique_lock<std::recursive_mutex> lock; |
525 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
526 | |
527 | StackFrame *frame = nullptr; |
528 | Target *target = exe_ctx.GetTargetPtr(); |
529 | Process *process = exe_ctx.GetProcessPtr(); |
530 | if (target && process) { |
531 | Process::StopLocker stop_locker; |
532 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
533 | frame = exe_ctx.GetFramePtr(); |
534 | if (frame) { |
535 | value_sp = frame->FindVariable(name: ConstString(name)); |
536 | |
537 | if (value_sp) |
538 | sb_value.SetSP(sp: value_sp, use_dynamic); |
539 | } |
540 | } |
541 | } |
542 | |
543 | return sb_value; |
544 | } |
545 | |
546 | SBValue SBFrame::FindValue(const char *name, ValueType value_type) { |
547 | LLDB_INSTRUMENT_VA(this, name, value_type); |
548 | |
549 | SBValue value; |
550 | std::unique_lock<std::recursive_mutex> lock; |
551 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
552 | |
553 | StackFrame *frame = exe_ctx.GetFramePtr(); |
554 | Target *target = exe_ctx.GetTargetPtr(); |
555 | if (frame && target) { |
556 | lldb::DynamicValueType use_dynamic = |
557 | frame->CalculateTarget()->GetPreferDynamicValue(); |
558 | value = FindValue(name, value_type, use_dynamic); |
559 | } |
560 | return value; |
561 | } |
562 | |
563 | SBValue SBFrame::FindValue(const char *name, ValueType value_type, |
564 | lldb::DynamicValueType use_dynamic) { |
565 | LLDB_INSTRUMENT_VA(this, name, value_type, use_dynamic); |
566 | |
567 | SBValue sb_value; |
568 | |
569 | if (name == nullptr || name[0] == '\0') { |
570 | return sb_value; |
571 | } |
572 | |
573 | ValueObjectSP value_sp; |
574 | std::unique_lock<std::recursive_mutex> lock; |
575 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
576 | |
577 | StackFrame *frame = nullptr; |
578 | Target *target = exe_ctx.GetTargetPtr(); |
579 | Process *process = exe_ctx.GetProcessPtr(); |
580 | if (target && process) { |
581 | Process::StopLocker stop_locker; |
582 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
583 | frame = exe_ctx.GetFramePtr(); |
584 | if (frame) { |
585 | VariableList variable_list; |
586 | |
587 | switch (value_type) { |
588 | case eValueTypeVariableGlobal: // global variable |
589 | case eValueTypeVariableStatic: // static variable |
590 | case eValueTypeVariableArgument: // function argument variables |
591 | case eValueTypeVariableLocal: // function local variables |
592 | case eValueTypeVariableThreadLocal: // thread local variables |
593 | { |
594 | SymbolContext sc(frame->GetSymbolContext(resolve_scope: eSymbolContextBlock)); |
595 | |
596 | const bool can_create = true; |
597 | const bool get_parent_variables = true; |
598 | const bool stop_if_block_is_inlined_function = true; |
599 | |
600 | if (sc.block) |
601 | sc.block->AppendVariables( |
602 | can_create, get_parent_variables, |
603 | stop_if_block_is_inlined_function, |
604 | filter: [frame](Variable *v) { return v->IsInScope(frame); }, |
605 | variable_list: &variable_list); |
606 | if (value_type == eValueTypeVariableGlobal |
607 | || value_type == eValueTypeVariableStatic) { |
608 | const bool get_file_globals = true; |
609 | VariableList *frame_vars = frame->GetVariableList(get_file_globals, |
610 | error_ptr: nullptr); |
611 | if (frame_vars) |
612 | frame_vars->AppendVariablesIfUnique(var_list&: variable_list); |
613 | } |
614 | ConstString const_name(name); |
615 | VariableSP variable_sp( |
616 | variable_list.FindVariable(name: const_name, value_type)); |
617 | if (variable_sp) { |
618 | value_sp = frame->GetValueObjectForFrameVariable(variable_sp, |
619 | use_dynamic: eNoDynamicValues); |
620 | sb_value.SetSP(sp: value_sp, use_dynamic); |
621 | } |
622 | } break; |
623 | |
624 | case eValueTypeRegister: // stack frame register value |
625 | { |
626 | RegisterContextSP reg_ctx(frame->GetRegisterContext()); |
627 | if (reg_ctx) { |
628 | if (const RegisterInfo *reg_info = |
629 | reg_ctx->GetRegisterInfoByName(reg_name: name)) { |
630 | value_sp = ValueObjectRegister::Create(exe_scope: frame, reg_ctx_sp&: reg_ctx, reg_info); |
631 | sb_value.SetSP(value_sp); |
632 | } |
633 | } |
634 | } break; |
635 | |
636 | case eValueTypeRegisterSet: // A collection of stack frame register |
637 | // values |
638 | { |
639 | RegisterContextSP reg_ctx(frame->GetRegisterContext()); |
640 | if (reg_ctx) { |
641 | const uint32_t num_sets = reg_ctx->GetRegisterSetCount(); |
642 | for (uint32_t set_idx = 0; set_idx < num_sets; ++set_idx) { |
643 | const RegisterSet *reg_set = reg_ctx->GetRegisterSet(reg_set: set_idx); |
644 | if (reg_set && |
645 | (llvm::StringRef(reg_set->name).equals_insensitive(RHS: name) || |
646 | llvm::StringRef(reg_set->short_name) |
647 | .equals_insensitive(RHS: name))) { |
648 | value_sp = |
649 | ValueObjectRegisterSet::Create(exe_scope: frame, reg_ctx_sp&: reg_ctx, set_idx); |
650 | sb_value.SetSP(value_sp); |
651 | break; |
652 | } |
653 | } |
654 | } |
655 | } break; |
656 | |
657 | case eValueTypeConstResult: // constant result variables |
658 | { |
659 | ConstString const_name(name); |
660 | ExpressionVariableSP expr_var_sp( |
661 | target->GetPersistentVariable(name: const_name)); |
662 | if (expr_var_sp) { |
663 | value_sp = expr_var_sp->GetValueObject(); |
664 | sb_value.SetSP(sp: value_sp, use_dynamic); |
665 | } |
666 | } break; |
667 | |
668 | default: |
669 | break; |
670 | } |
671 | } |
672 | } |
673 | } |
674 | |
675 | return sb_value; |
676 | } |
677 | |
678 | bool SBFrame::IsEqual(const SBFrame &that) const { |
679 | LLDB_INSTRUMENT_VA(this, that); |
680 | |
681 | lldb::StackFrameSP this_sp = GetFrameSP(); |
682 | lldb::StackFrameSP that_sp = that.GetFrameSP(); |
683 | return (this_sp && that_sp && this_sp->GetStackID() == that_sp->GetStackID()); |
684 | } |
685 | |
686 | bool SBFrame::operator==(const SBFrame &rhs) const { |
687 | LLDB_INSTRUMENT_VA(this, rhs); |
688 | |
689 | return IsEqual(that: rhs); |
690 | } |
691 | |
692 | bool SBFrame::operator!=(const SBFrame &rhs) const { |
693 | LLDB_INSTRUMENT_VA(this, rhs); |
694 | |
695 | return !IsEqual(that: rhs); |
696 | } |
697 | |
698 | SBThread SBFrame::GetThread() const { |
699 | LLDB_INSTRUMENT_VA(this); |
700 | |
701 | std::unique_lock<std::recursive_mutex> lock; |
702 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
703 | |
704 | ThreadSP thread_sp(exe_ctx.GetThreadSP()); |
705 | SBThread sb_thread(thread_sp); |
706 | |
707 | return sb_thread; |
708 | } |
709 | |
710 | const char *SBFrame::Disassemble() const { |
711 | LLDB_INSTRUMENT_VA(this); |
712 | |
713 | std::unique_lock<std::recursive_mutex> lock; |
714 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
715 | Target *target = exe_ctx.GetTargetPtr(); |
716 | Process *process = exe_ctx.GetProcessPtr(); |
717 | if (!target || !process) |
718 | return nullptr; |
719 | |
720 | Process::StopLocker stop_locker; |
721 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
722 | if (auto *frame = exe_ctx.GetFramePtr()) |
723 | return ConstString(frame->Disassemble()).GetCString(); |
724 | } |
725 | |
726 | return nullptr; |
727 | } |
728 | |
729 | SBValueList SBFrame::GetVariables(bool arguments, bool locals, bool statics, |
730 | bool in_scope_only) { |
731 | LLDB_INSTRUMENT_VA(this, arguments, locals, statics, in_scope_only); |
732 | |
733 | SBValueList value_list; |
734 | std::unique_lock<std::recursive_mutex> lock; |
735 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
736 | |
737 | StackFrame *frame = exe_ctx.GetFramePtr(); |
738 | Target *target = exe_ctx.GetTargetPtr(); |
739 | if (frame && target) { |
740 | lldb::DynamicValueType use_dynamic = |
741 | frame->CalculateTarget()->GetPreferDynamicValue(); |
742 | const bool include_runtime_support_values = |
743 | target->GetDisplayRuntimeSupportValues(); |
744 | |
745 | SBVariablesOptions options; |
746 | options.SetIncludeArguments(arguments); |
747 | options.SetIncludeLocals(locals); |
748 | options.SetIncludeStatics(statics); |
749 | options.SetInScopeOnly(in_scope_only); |
750 | options.SetIncludeRuntimeSupportValues(include_runtime_support_values); |
751 | options.SetUseDynamic(use_dynamic); |
752 | |
753 | value_list = GetVariables(options); |
754 | } |
755 | return value_list; |
756 | } |
757 | |
758 | lldb::SBValueList SBFrame::GetVariables(bool arguments, bool locals, |
759 | bool statics, bool in_scope_only, |
760 | lldb::DynamicValueType use_dynamic) { |
761 | LLDB_INSTRUMENT_VA(this, arguments, locals, statics, in_scope_only, |
762 | use_dynamic); |
763 | |
764 | std::unique_lock<std::recursive_mutex> lock; |
765 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
766 | |
767 | Target *target = exe_ctx.GetTargetPtr(); |
768 | const bool include_runtime_support_values = |
769 | target ? target->GetDisplayRuntimeSupportValues() : false; |
770 | SBVariablesOptions options; |
771 | options.SetIncludeArguments(arguments); |
772 | options.SetIncludeLocals(locals); |
773 | options.SetIncludeStatics(statics); |
774 | options.SetInScopeOnly(in_scope_only); |
775 | options.SetIncludeRuntimeSupportValues(include_runtime_support_values); |
776 | options.SetUseDynamic(use_dynamic); |
777 | return GetVariables(options); |
778 | } |
779 | |
780 | SBValueList SBFrame::GetVariables(const lldb::SBVariablesOptions &options) { |
781 | LLDB_INSTRUMENT_VA(this, options); |
782 | |
783 | SBValueList value_list; |
784 | std::unique_lock<std::recursive_mutex> lock; |
785 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
786 | |
787 | StackFrame *frame = nullptr; |
788 | Target *target = exe_ctx.GetTargetPtr(); |
789 | |
790 | const bool statics = options.GetIncludeStatics(); |
791 | const bool arguments = options.GetIncludeArguments(); |
792 | const bool recognized_arguments = |
793 | options.GetIncludeRecognizedArguments(SBTarget(exe_ctx.GetTargetSP())); |
794 | const bool locals = options.GetIncludeLocals(); |
795 | const bool in_scope_only = options.GetInScopeOnly(); |
796 | const bool include_runtime_support_values = |
797 | options.GetIncludeRuntimeSupportValues(); |
798 | const lldb::DynamicValueType use_dynamic = options.GetUseDynamic(); |
799 | |
800 | |
801 | std::set<VariableSP> variable_set; |
802 | Process *process = exe_ctx.GetProcessPtr(); |
803 | if (target && process) { |
804 | Process::StopLocker stop_locker; |
805 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
806 | frame = exe_ctx.GetFramePtr(); |
807 | if (frame) { |
808 | Debugger &dbg = process->GetTarget().GetDebugger(); |
809 | VariableList *variable_list = nullptr; |
810 | Status var_error; |
811 | variable_list = frame->GetVariableList(get_file_globals: true, error_ptr: &var_error); |
812 | if (var_error.Fail()) |
813 | value_list.SetError(std::move(var_error)); |
814 | if (variable_list) { |
815 | const size_t num_variables = variable_list->GetSize(); |
816 | if (num_variables) { |
817 | size_t num_produced = 0; |
818 | for (const VariableSP &variable_sp : *variable_list) { |
819 | if (INTERRUPT_REQUESTED(dbg, |
820 | "Interrupted getting frame variables with {0} of {1} " |
821 | "produced.", num_produced, num_variables)) |
822 | return {}; |
823 | |
824 | if (variable_sp) { |
825 | bool add_variable = false; |
826 | switch (variable_sp->GetScope()) { |
827 | case eValueTypeVariableGlobal: |
828 | case eValueTypeVariableStatic: |
829 | case eValueTypeVariableThreadLocal: |
830 | add_variable = statics; |
831 | break; |
832 | |
833 | case eValueTypeVariableArgument: |
834 | add_variable = arguments; |
835 | break; |
836 | |
837 | case eValueTypeVariableLocal: |
838 | add_variable = locals; |
839 | break; |
840 | |
841 | default: |
842 | break; |
843 | } |
844 | if (add_variable) { |
845 | // Only add variables once so we don't end up with duplicates |
846 | if (variable_set.find(x: variable_sp) == variable_set.end()) |
847 | variable_set.insert(x: variable_sp); |
848 | else |
849 | continue; |
850 | |
851 | if (in_scope_only && !variable_sp->IsInScope(frame)) |
852 | continue; |
853 | |
854 | ValueObjectSP valobj_sp(frame->GetValueObjectForFrameVariable( |
855 | variable_sp, use_dynamic: eNoDynamicValues)); |
856 | |
857 | if (!include_runtime_support_values && valobj_sp != nullptr && |
858 | valobj_sp->IsRuntimeSupportValue()) |
859 | continue; |
860 | |
861 | SBValue value_sb; |
862 | value_sb.SetSP(sp: valobj_sp, use_dynamic); |
863 | value_list.Append(val_obj: value_sb); |
864 | } |
865 | } |
866 | } |
867 | num_produced++; |
868 | } |
869 | } |
870 | if (recognized_arguments) { |
871 | auto recognized_frame = frame->GetRecognizedFrame(); |
872 | if (recognized_frame) { |
873 | ValueObjectListSP recognized_arg_list = |
874 | recognized_frame->GetRecognizedArguments(); |
875 | if (recognized_arg_list) { |
876 | for (auto &rec_value_sp : recognized_arg_list->GetObjects()) { |
877 | SBValue value_sb; |
878 | value_sb.SetSP(sp: rec_value_sp, use_dynamic); |
879 | value_list.Append(val_obj: value_sb); |
880 | } |
881 | } |
882 | } |
883 | } |
884 | } |
885 | } |
886 | } |
887 | |
888 | return value_list; |
889 | } |
890 | |
891 | SBValueList SBFrame::GetRegisters() { |
892 | LLDB_INSTRUMENT_VA(this); |
893 | |
894 | SBValueList value_list; |
895 | std::unique_lock<std::recursive_mutex> lock; |
896 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
897 | |
898 | StackFrame *frame = nullptr; |
899 | Target *target = exe_ctx.GetTargetPtr(); |
900 | Process *process = exe_ctx.GetProcessPtr(); |
901 | if (target && process) { |
902 | Process::StopLocker stop_locker; |
903 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
904 | frame = exe_ctx.GetFramePtr(); |
905 | if (frame) { |
906 | RegisterContextSP reg_ctx(frame->GetRegisterContext()); |
907 | if (reg_ctx) { |
908 | const uint32_t num_sets = reg_ctx->GetRegisterSetCount(); |
909 | for (uint32_t set_idx = 0; set_idx < num_sets; ++set_idx) { |
910 | value_list.Append( |
911 | val_obj: ValueObjectRegisterSet::Create(exe_scope: frame, reg_ctx_sp&: reg_ctx, set_idx)); |
912 | } |
913 | } |
914 | } |
915 | } |
916 | } |
917 | |
918 | return value_list; |
919 | } |
920 | |
921 | SBValue SBFrame::FindRegister(const char *name) { |
922 | LLDB_INSTRUMENT_VA(this, name); |
923 | |
924 | SBValue result; |
925 | ValueObjectSP value_sp; |
926 | std::unique_lock<std::recursive_mutex> lock; |
927 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
928 | |
929 | StackFrame *frame = nullptr; |
930 | Target *target = exe_ctx.GetTargetPtr(); |
931 | Process *process = exe_ctx.GetProcessPtr(); |
932 | if (target && process) { |
933 | Process::StopLocker stop_locker; |
934 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
935 | frame = exe_ctx.GetFramePtr(); |
936 | if (frame) { |
937 | RegisterContextSP reg_ctx(frame->GetRegisterContext()); |
938 | if (reg_ctx) { |
939 | if (const RegisterInfo *reg_info = |
940 | reg_ctx->GetRegisterInfoByName(reg_name: name)) { |
941 | value_sp = ValueObjectRegister::Create(exe_scope: frame, reg_ctx_sp&: reg_ctx, reg_info); |
942 | result.SetSP(value_sp); |
943 | } |
944 | } |
945 | } |
946 | } |
947 | } |
948 | |
949 | return result; |
950 | } |
951 | |
952 | SBError SBFrame::GetDescriptionWithFormat(const SBFormat &format, |
953 | SBStream &output) { |
954 | Stream &strm = output.ref(); |
955 | |
956 | std::unique_lock<std::recursive_mutex> lock; |
957 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
958 | |
959 | StackFrame *frame = nullptr; |
960 | Target *target = exe_ctx.GetTargetPtr(); |
961 | Process *process = exe_ctx.GetProcessPtr(); |
962 | SBError error; |
963 | |
964 | if (!format) { |
965 | error.SetErrorString("The provided SBFormat object is invalid"); |
966 | return error; |
967 | } |
968 | |
969 | if (target && process) { |
970 | Process::StopLocker stop_locker; |
971 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
972 | frame = exe_ctx.GetFramePtr(); |
973 | if (frame && |
974 | frame->DumpUsingFormat(strm, format: format.GetFormatEntrySP().get())) { |
975 | return error; |
976 | } |
977 | } |
978 | } |
979 | error.SetErrorStringWithFormat( |
980 | "It was not possible to generate a frame " |
981 | "description with the given format string '%s'", |
982 | format.GetFormatEntrySP()->string.c_str()); |
983 | return error; |
984 | } |
985 | |
986 | bool SBFrame::GetDescription(SBStream &description) { |
987 | LLDB_INSTRUMENT_VA(this, description); |
988 | |
989 | Stream &strm = description.ref(); |
990 | |
991 | std::unique_lock<std::recursive_mutex> lock; |
992 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
993 | |
994 | StackFrame *frame; |
995 | Target *target = exe_ctx.GetTargetPtr(); |
996 | Process *process = exe_ctx.GetProcessPtr(); |
997 | if (target && process) { |
998 | Process::StopLocker stop_locker; |
999 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
1000 | frame = exe_ctx.GetFramePtr(); |
1001 | if (frame) { |
1002 | frame->DumpUsingSettingsFormat(strm: &strm); |
1003 | } |
1004 | } |
1005 | |
1006 | } else |
1007 | strm.PutCString(cstr: "No value"); |
1008 | |
1009 | return true; |
1010 | } |
1011 | |
1012 | SBValue SBFrame::EvaluateExpression(const char *expr) { |
1013 | LLDB_INSTRUMENT_VA(this, expr); |
1014 | |
1015 | std::unique_lock<std::recursive_mutex> lock; |
1016 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
1017 | |
1018 | StackFrame *frame = exe_ctx.GetFramePtr(); |
1019 | Target *target = exe_ctx.GetTargetPtr(); |
1020 | SBExpressionOptions options; |
1021 | if (frame && target) { |
1022 | lldb::DynamicValueType fetch_dynamic_value = |
1023 | frame->CalculateTarget()->GetPreferDynamicValue(); |
1024 | options.SetFetchDynamicValue(fetch_dynamic_value); |
1025 | } |
1026 | options.SetUnwindOnError(true); |
1027 | options.SetIgnoreBreakpoints(true); |
1028 | SourceLanguage language; |
1029 | if (target) |
1030 | language = target->GetLanguage(); |
1031 | if (!language && frame) |
1032 | language = frame->GetLanguage(); |
1033 | options.SetLanguage(name: (SBSourceLanguageName)language.name, version: language.version); |
1034 | return EvaluateExpression(expr, options); |
1035 | } |
1036 | |
1037 | SBValue |
1038 | SBFrame::EvaluateExpression(const char *expr, |
1039 | lldb::DynamicValueType fetch_dynamic_value) { |
1040 | LLDB_INSTRUMENT_VA(this, expr, fetch_dynamic_value); |
1041 | |
1042 | SBExpressionOptions options; |
1043 | options.SetFetchDynamicValue(fetch_dynamic_value); |
1044 | options.SetUnwindOnError(true); |
1045 | options.SetIgnoreBreakpoints(true); |
1046 | std::unique_lock<std::recursive_mutex> lock; |
1047 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
1048 | |
1049 | StackFrame *frame = exe_ctx.GetFramePtr(); |
1050 | Target *target = exe_ctx.GetTargetPtr(); |
1051 | SourceLanguage language; |
1052 | if (target) |
1053 | language = target->GetLanguage(); |
1054 | if (!language && frame) |
1055 | language = frame->GetLanguage(); |
1056 | options.SetLanguage(name: (SBSourceLanguageName)language.name, version: language.version); |
1057 | return EvaluateExpression(expr, options); |
1058 | } |
1059 | |
1060 | SBValue SBFrame::EvaluateExpression(const char *expr, |
1061 | lldb::DynamicValueType fetch_dynamic_value, |
1062 | bool unwind_on_error) { |
1063 | LLDB_INSTRUMENT_VA(this, expr, fetch_dynamic_value, unwind_on_error); |
1064 | |
1065 | SBExpressionOptions options; |
1066 | std::unique_lock<std::recursive_mutex> lock; |
1067 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
1068 | |
1069 | options.SetFetchDynamicValue(fetch_dynamic_value); |
1070 | options.SetUnwindOnError(unwind_on_error); |
1071 | options.SetIgnoreBreakpoints(true); |
1072 | StackFrame *frame = exe_ctx.GetFramePtr(); |
1073 | Target *target = exe_ctx.GetTargetPtr(); |
1074 | SourceLanguage language; |
1075 | if (target) |
1076 | language = target->GetLanguage(); |
1077 | if (!language && frame) |
1078 | language = frame->GetLanguage(); |
1079 | options.SetLanguage(name: (SBSourceLanguageName)language.name, version: language.version); |
1080 | return EvaluateExpression(expr, options); |
1081 | } |
1082 | |
1083 | lldb::SBValue SBFrame::EvaluateExpression(const char *expr, |
1084 | const SBExpressionOptions &options) { |
1085 | LLDB_INSTRUMENT_VA(this, expr, options); |
1086 | |
1087 | Log *expr_log = GetLog(mask: LLDBLog::Expressions); |
1088 | |
1089 | SBValue expr_result; |
1090 | |
1091 | if (expr == nullptr || expr[0] == '\0') { |
1092 | return expr_result; |
1093 | } |
1094 | |
1095 | ValueObjectSP expr_value_sp; |
1096 | |
1097 | std::unique_lock<std::recursive_mutex> lock; |
1098 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
1099 | |
1100 | StackFrame *frame = nullptr; |
1101 | Target *target = exe_ctx.GetTargetPtr(); |
1102 | Process *process = exe_ctx.GetProcessPtr(); |
1103 | |
1104 | if (target && process) { |
1105 | Process::StopLocker stop_locker; |
1106 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
1107 | frame = exe_ctx.GetFramePtr(); |
1108 | if (frame) { |
1109 | std::unique_ptr<llvm::PrettyStackTraceFormat> stack_trace; |
1110 | if (target->GetDisplayExpressionsInCrashlogs()) { |
1111 | StreamString frame_description; |
1112 | frame->DumpUsingSettingsFormat(strm: &frame_description); |
1113 | stack_trace = std::make_unique<llvm::PrettyStackTraceFormat>( |
1114 | args: "SBFrame::EvaluateExpression (expr = \"%s\", fetch_dynamic_value " |
1115 | "= %u) %s", |
1116 | args&: expr, args: options.GetFetchDynamicValue(), |
1117 | args: frame_description.GetData()); |
1118 | } |
1119 | |
1120 | target->EvaluateExpression(expression: expr, exe_scope: frame, result_valobj_sp&: expr_value_sp, options: options.ref()); |
1121 | expr_result.SetSP(sp: expr_value_sp, use_dynamic: options.GetFetchDynamicValue()); |
1122 | } |
1123 | } else { |
1124 | Status error; |
1125 | error = Status::FromErrorString(str: "can't evaluate expressions when the " |
1126 | "process is running."); |
1127 | expr_value_sp = ValueObjectConstResult::Create(exe_scope: nullptr, error: std::move(error)); |
1128 | expr_result.SetSP(sp: expr_value_sp, use_synthetic: false); |
1129 | } |
1130 | } else { |
1131 | Status error; |
1132 | error = Status::FromErrorString(str: "sbframe object is not valid."); |
1133 | expr_value_sp = ValueObjectConstResult::Create(exe_scope: nullptr, error: std::move(error)); |
1134 | expr_result.SetSP(sp: expr_value_sp, use_synthetic: false); |
1135 | } |
1136 | |
1137 | if (expr_result.GetError().Success()) |
1138 | LLDB_LOGF(expr_log, |
1139 | "** [SBFrame::EvaluateExpression] Expression result is " |
1140 | "%s, summary %s **", |
1141 | expr_result.GetValue(), expr_result.GetSummary()); |
1142 | else |
1143 | LLDB_LOGF(expr_log, |
1144 | "** [SBFrame::EvaluateExpression] Expression evaluation failed: " |
1145 | "%s **", |
1146 | expr_result.GetError().GetCString()); |
1147 | |
1148 | return expr_result; |
1149 | } |
1150 | |
1151 | SBStructuredData SBFrame::GetLanguageSpecificData() const { |
1152 | LLDB_INSTRUMENT_VA(this); |
1153 | |
1154 | SBStructuredData sb_data; |
1155 | std::unique_lock<std::recursive_mutex> lock; |
1156 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
1157 | StackFrame *frame = exe_ctx.GetFramePtr(); |
1158 | if (!frame) |
1159 | return sb_data; |
1160 | |
1161 | StructuredData::ObjectSP data(frame->GetLanguageSpecificData()); |
1162 | sb_data.m_impl_up->SetObjectSP(data); |
1163 | return sb_data; |
1164 | } |
1165 | |
1166 | bool SBFrame::IsInlined() { |
1167 | LLDB_INSTRUMENT_VA(this); |
1168 | |
1169 | return static_cast<const SBFrame *>(this)->IsInlined(); |
1170 | } |
1171 | |
1172 | bool SBFrame::IsInlined() const { |
1173 | LLDB_INSTRUMENT_VA(this); |
1174 | |
1175 | std::unique_lock<std::recursive_mutex> lock; |
1176 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
1177 | |
1178 | StackFrame *frame = nullptr; |
1179 | Target *target = exe_ctx.GetTargetPtr(); |
1180 | Process *process = exe_ctx.GetProcessPtr(); |
1181 | if (target && process) { |
1182 | Process::StopLocker stop_locker; |
1183 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
1184 | frame = exe_ctx.GetFramePtr(); |
1185 | if (frame) |
1186 | return frame->IsInlined(); |
1187 | } |
1188 | } |
1189 | return false; |
1190 | } |
1191 | |
1192 | bool SBFrame::IsArtificial() { |
1193 | LLDB_INSTRUMENT_VA(this); |
1194 | |
1195 | return static_cast<const SBFrame *>(this)->IsArtificial(); |
1196 | } |
1197 | |
1198 | bool SBFrame::IsArtificial() const { |
1199 | LLDB_INSTRUMENT_VA(this); |
1200 | |
1201 | std::unique_lock<std::recursive_mutex> lock; |
1202 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
1203 | |
1204 | if (StackFrame *frame = exe_ctx.GetFramePtr()) |
1205 | return frame->IsArtificial(); |
1206 | |
1207 | return false; |
1208 | } |
1209 | |
1210 | bool SBFrame::IsHidden() const { |
1211 | LLDB_INSTRUMENT_VA(this); |
1212 | |
1213 | std::unique_lock<std::recursive_mutex> lock; |
1214 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
1215 | |
1216 | if (StackFrame *frame = exe_ctx.GetFramePtr()) |
1217 | return frame->IsHidden(); |
1218 | |
1219 | return false; |
1220 | } |
1221 | |
1222 | const char *SBFrame::GetFunctionName() { |
1223 | LLDB_INSTRUMENT_VA(this); |
1224 | |
1225 | return static_cast<const SBFrame *>(this)->GetFunctionName(); |
1226 | } |
1227 | |
1228 | lldb::LanguageType SBFrame::GuessLanguage() const { |
1229 | LLDB_INSTRUMENT_VA(this); |
1230 | |
1231 | std::unique_lock<std::recursive_mutex> lock; |
1232 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
1233 | |
1234 | StackFrame *frame = nullptr; |
1235 | Target *target = exe_ctx.GetTargetPtr(); |
1236 | Process *process = exe_ctx.GetProcessPtr(); |
1237 | if (target && process) { |
1238 | Process::StopLocker stop_locker; |
1239 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
1240 | frame = exe_ctx.GetFramePtr(); |
1241 | if (frame) { |
1242 | return frame->GuessLanguage().AsLanguageType(); |
1243 | } |
1244 | } |
1245 | } |
1246 | return eLanguageTypeUnknown; |
1247 | } |
1248 | |
1249 | const char *SBFrame::GetFunctionName() const { |
1250 | LLDB_INSTRUMENT_VA(this); |
1251 | |
1252 | const char *name = nullptr; |
1253 | std::unique_lock<std::recursive_mutex> lock; |
1254 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
1255 | |
1256 | StackFrame *frame = nullptr; |
1257 | Target *target = exe_ctx.GetTargetPtr(); |
1258 | Process *process = exe_ctx.GetProcessPtr(); |
1259 | if (target && process) { |
1260 | Process::StopLocker stop_locker; |
1261 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
1262 | frame = exe_ctx.GetFramePtr(); |
1263 | if (frame) |
1264 | return frame->GetFunctionName(); |
1265 | } |
1266 | } |
1267 | return name; |
1268 | } |
1269 | |
1270 | const char *SBFrame::GetDisplayFunctionName() { |
1271 | LLDB_INSTRUMENT_VA(this); |
1272 | |
1273 | const char *name = nullptr; |
1274 | |
1275 | std::unique_lock<std::recursive_mutex> lock; |
1276 | ExecutionContext exe_ctx(m_opaque_sp.get(), lock); |
1277 | |
1278 | StackFrame *frame = nullptr; |
1279 | Target *target = exe_ctx.GetTargetPtr(); |
1280 | Process *process = exe_ctx.GetProcessPtr(); |
1281 | if (target && process) { |
1282 | Process::StopLocker stop_locker; |
1283 | if (stop_locker.TryLock(lock: &process->GetRunLock())) { |
1284 | frame = exe_ctx.GetFramePtr(); |
1285 | if (frame) |
1286 | return frame->GetDisplayFunctionName(); |
1287 | } |
1288 | } |
1289 | return name; |
1290 | } |
1291 |
Definitions
- SBFrame
- SBFrame
- SBFrame
- ~SBFrame
- operator=
- GetFrameSP
- SetFrameSP
- IsValid
- operator bool
- GetSymbolContext
- GetModule
- GetCompileUnit
- GetFunction
- GetSymbol
- GetBlock
- GetFrameBlock
- GetLineEntry
- GetFrameID
- GetCFA
- GetPC
- SetPC
- GetSP
- GetFP
- GetPCAddress
- Clear
- GetValueForVariablePath
- GetValueForVariablePath
- FindVariable
- FindVariable
- FindValue
- FindValue
- IsEqual
- operator==
- operator!=
- GetThread
- Disassemble
- GetVariables
- GetVariables
- GetVariables
- GetRegisters
- FindRegister
- GetDescriptionWithFormat
- GetDescription
- EvaluateExpression
- EvaluateExpression
- EvaluateExpression
- EvaluateExpression
- GetLanguageSpecificData
- IsInlined
- IsInlined
- IsArtificial
- IsArtificial
- IsHidden
- GetFunctionName
- GuessLanguage
- GetFunctionName
Learn to use CMake with our Intro Training
Find out more