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