LLDB mainline
Materializer.cpp
Go to the documentation of this file.
1//===-- Materializer.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
12#include "lldb/Symbol/Symbol.h"
13#include "lldb/Symbol/Type.h"
18#include "lldb/Target/Target.h"
19#include "lldb/Target/Thread.h"
21#include "lldb/Utility/Log.h"
25#include "lldb/lldb-forward.h"
26
27#include <memory>
28#include <optional>
29
30using namespace lldb_private;
31
32// FIXME: these should be retrieved from the target
33// instead of being hard-coded. Currently we
34// assume that persistent vars are materialized
35// as references, and thus pick the size of a
36// 64-bit pointer.
37static constexpr uint32_t g_default_var_alignment = 8;
38static constexpr uint32_t g_default_var_byte_size = 8;
39
41 uint32_t size = entity.GetSize();
42 uint32_t alignment = entity.GetAlignment();
43
44 uint32_t ret;
45
46 if (m_current_offset == 0)
47 m_struct_alignment = alignment;
48
49 if (m_current_offset % alignment)
50 m_current_offset += (alignment - (m_current_offset % alignment));
51
52 ret = m_current_offset;
53
54 m_current_offset += size;
55
56 return ret;
57}
58
60public:
63 : Entity(), m_persistent_variable_sp(persistent_variable_sp),
64 m_delegate(delegate) {
65 // Hard-coding to maximum size of a pointer since persistent variables are
66 // materialized by reference
68 m_alignment = g_default_var_alignment;
69 }
70
72 Log *log = GetLog(LLDBLog::Expressions);
73
74 // Allocate a spare memory area to store the persistent variable's
75 // contents.
76
77 Status allocate_error;
78 const bool zero_memory = false;
79
80 lldb::addr_t mem = map.Malloc(
81 m_persistent_variable_sp->GetByteSize().value_or(0), 8,
82 lldb::ePermissionsReadable | lldb::ePermissionsWritable,
83 IRMemoryMap::eAllocationPolicyMirror, zero_memory, allocate_error);
84
85 if (!allocate_error.Success()) {
87 "couldn't allocate a memory area to store %s: %s",
88 m_persistent_variable_sp->GetName().GetCString(),
89 allocate_error.AsCString());
90 return;
91 }
92
93 LLDB_LOGF(log, "Allocated %s (0x%" PRIx64 ") successfully",
94 m_persistent_variable_sp->GetName().GetCString(), mem);
95
96 // Put the location of the spare memory into the live data of the
97 // ValueObject.
98
99 m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create(
101 m_persistent_variable_sp->GetCompilerType(),
102 m_persistent_variable_sp->GetName(), mem, eAddressTypeLoad,
103 map.GetAddressByteSize());
104
105 // Clear the flag if the variable will never be deallocated.
106
107 if (m_persistent_variable_sp->m_flags &
109 Status leak_error;
110 map.Leak(mem, leak_error);
111 m_persistent_variable_sp->m_flags &=
112 ~ExpressionVariable::EVNeedsAllocation;
113 }
114
115 // Write the contents of the variable to the area.
116
117 Status write_error;
118
119 map.WriteMemory(mem, m_persistent_variable_sp->GetValueBytes(),
120 m_persistent_variable_sp->GetByteSize().value_or(0),
121 write_error);
122
123 if (!write_error.Success()) {
125 "couldn't write %s to the target: %s",
126 m_persistent_variable_sp->GetName().AsCString(),
127 write_error.AsCString());
128 return;
129 }
130 }
131
133 Status deallocate_error;
134
135 map.Free((lldb::addr_t)m_persistent_variable_sp->m_live_sp->GetValue()
136 .GetScalar()
137 .ULongLong(),
138 deallocate_error);
139
140 m_persistent_variable_sp->m_live_sp.reset();
141
142 if (!deallocate_error.Success()) {
144 "couldn't deallocate memory for %s: %s",
145 m_persistent_variable_sp->GetName().GetCString(),
146 deallocate_error.AsCString());
147 }
148 }
149
151 lldb::addr_t process_address, Status &err) override {
152 Log *log = GetLog(LLDBLog::Expressions);
153
154 const lldb::addr_t load_addr = process_address + m_offset;
155
156 if (log) {
157 LLDB_LOGF(log,
158 "EntityPersistentVariable::Materialize [address = 0x%" PRIx64
159 ", m_name = %s, m_flags = 0x%hx]",
160 (uint64_t)load_addr,
161 m_persistent_variable_sp->GetName().AsCString(),
162 m_persistent_variable_sp->m_flags);
163 }
164
165 if (m_persistent_variable_sp->m_flags &
167 MakeAllocation(map, err);
168 m_persistent_variable_sp->m_flags |=
170
171 if (!err.Success())
172 return;
173 }
174
175 if ((m_persistent_variable_sp->m_flags &
177 m_persistent_variable_sp->m_live_sp) ||
178 m_persistent_variable_sp->m_flags &
180 Status write_error;
181
183 load_addr,
184 m_persistent_variable_sp->m_live_sp->GetValue().GetScalar(),
185 map.GetAddressByteSize(), write_error);
186
187 if (!write_error.Success()) {
189 "couldn't write the location of %s to memory: %s",
190 m_persistent_variable_sp->GetName().AsCString(),
191 write_error.AsCString());
192 }
193 } else {
195 "no materialization happened for persistent variable %s",
196 m_persistent_variable_sp->GetName().AsCString());
197 return;
198 }
199 }
200
202 lldb::addr_t process_address, lldb::addr_t frame_top,
203 lldb::addr_t frame_bottom, Status &err) override {
204 Log *log = GetLog(LLDBLog::Expressions);
205
206 const lldb::addr_t load_addr = process_address + m_offset;
207
208 if (log) {
209 LLDB_LOGF(log,
210 "EntityPersistentVariable::Dematerialize [address = 0x%" PRIx64
211 ", m_name = %s, m_flags = 0x%hx]",
212 (uint64_t)process_address + m_offset,
213 m_persistent_variable_sp->GetName().AsCString(),
214 m_persistent_variable_sp->m_flags);
215 }
216
217 if (m_delegate) {
218 m_delegate->DidDematerialize(m_persistent_variable_sp);
219 }
220
221 if ((m_persistent_variable_sp->m_flags &
223 (m_persistent_variable_sp->m_flags &
225 if (m_persistent_variable_sp->m_flags &
227 !m_persistent_variable_sp->m_live_sp) {
228 // If the reference comes from the program, then the
229 // ClangExpressionVariable's live variable data hasn't been set up yet.
230 // Do this now.
231
232 lldb::addr_t location;
233 Status read_error;
234
235 map.ReadPointerFromMemory(&location, load_addr, read_error);
236
237 if (!read_error.Success()) {
239 "couldn't read the address of program-allocated variable %s: %s",
240 m_persistent_variable_sp->GetName().GetCString(),
241 read_error.AsCString());
242 return;
243 }
244
245 m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create(
247 m_persistent_variable_sp.get()->GetCompilerType(),
248 m_persistent_variable_sp->GetName(), location, eAddressTypeLoad,
249 m_persistent_variable_sp->GetByteSize().value_or(0));
250
251 if (frame_top != LLDB_INVALID_ADDRESS &&
252 frame_bottom != LLDB_INVALID_ADDRESS && location >= frame_bottom &&
253 location <= frame_top) {
254 // If the variable is resident in the stack frame created by the
255 // expression, then it cannot be relied upon to stay around. We
256 // treat it as needing reallocation.
257 m_persistent_variable_sp->m_flags |=
259 m_persistent_variable_sp->m_flags |=
261 m_persistent_variable_sp->m_flags |=
263 m_persistent_variable_sp->m_flags &=
264 ~ExpressionVariable::EVIsProgramReference;
265 }
266 }
267
268 lldb::addr_t mem = m_persistent_variable_sp->m_live_sp->GetValue()
269 .GetScalar()
270 .ULongLong();
271
272 if (!m_persistent_variable_sp->m_live_sp) {
274 "couldn't find the memory area used to store %s",
275 m_persistent_variable_sp->GetName().GetCString());
276 return;
277 }
278
279 if (m_persistent_variable_sp->m_live_sp->GetValue()
280 .GetValueAddressType() != eAddressTypeLoad) {
282 "the address of the memory area for %s is in an incorrect format",
283 m_persistent_variable_sp->GetName().GetCString());
284 return;
285 }
286
287 if (m_persistent_variable_sp->m_flags &
289 m_persistent_variable_sp->m_flags &
291 LLDB_LOGF(log, "Dematerializing %s from 0x%" PRIx64 " (size = %llu)",
292 m_persistent_variable_sp->GetName().GetCString(),
293 (uint64_t)mem,
294 (unsigned long long)m_persistent_variable_sp->GetByteSize()
295 .value_or(0));
296
297 // Read the contents of the spare memory area
298
299 m_persistent_variable_sp->ValueUpdated();
300
301 Status read_error;
302
303 map.ReadMemory(m_persistent_variable_sp->GetValueBytes(), mem,
304 m_persistent_variable_sp->GetByteSize().value_or(0),
305 read_error);
306
307 if (!read_error.Success()) {
309 "couldn't read the contents of %s from memory: %s",
310 m_persistent_variable_sp->GetName().GetCString(),
311 read_error.AsCString());
312 return;
313 }
314
315 m_persistent_variable_sp->m_flags &=
316 ~ExpressionVariable::EVNeedsFreezeDry;
317 }
318 } else {
320 "no dematerialization happened for persistent variable %s",
321 m_persistent_variable_sp->GetName().AsCString());
322 return;
323 }
324
325 lldb::ProcessSP process_sp =
327 if (!process_sp || !process_sp->CanJIT()) {
328 // Allocations are not persistent so persistent variables cannot stay
329 // materialized.
330
331 m_persistent_variable_sp->m_flags |=
333
334 DestroyAllocation(map, err);
335 if (!err.Success())
336 return;
337 } else if (m_persistent_variable_sp->m_flags &
339 !(m_persistent_variable_sp->m_flags &
341 DestroyAllocation(map, err);
342 if (!err.Success())
343 return;
344 }
345 }
346
347 void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
348 Log *log) override {
349 StreamString dump_stream;
350
351 Status err;
352
353 const lldb::addr_t load_addr = process_address + m_offset;
354
355 dump_stream.Printf("0x%" PRIx64 ": EntityPersistentVariable (%s)\n",
356 load_addr,
357 m_persistent_variable_sp->GetName().AsCString());
358
359 {
360 dump_stream.Printf("Pointer:\n");
361
362 DataBufferHeap data(m_size, 0);
363
364 map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
365
366 if (!err.Success()) {
367 dump_stream.Printf(" <could not be read>\n");
368 } else {
369 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
370 load_addr);
371
372 dump_stream.PutChar('\n');
373 }
374 }
375
376 {
377 dump_stream.Printf("Target:\n");
378
379 lldb::addr_t target_address;
380
381 map.ReadPointerFromMemory(&target_address, load_addr, err);
382
383 if (!err.Success()) {
384 dump_stream.Printf(" <could not be read>\n");
385 } else {
386 DataBufferHeap data(m_persistent_variable_sp->GetByteSize().value_or(0),
387 0);
388
389 map.ReadMemory(data.GetBytes(), target_address,
390 m_persistent_variable_sp->GetByteSize().value_or(0),
391 err);
392
393 if (!err.Success()) {
394 dump_stream.Printf(" <could not be read>\n");
395 } else {
396 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
397 target_address);
398
399 dump_stream.PutChar('\n');
400 }
401 }
402 }
403
404 log->PutString(dump_stream.GetString());
405 }
406
407 void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}
408
409private:
412};
413
415 lldb::ExpressionVariableSP &persistent_variable_sp,
416 PersistentVariableDelegate *delegate, Status &err) {
417 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
418 *iter = std::make_unique<EntityPersistentVariable>(persistent_variable_sp,
419 delegate);
420 uint32_t ret = AddStructMember(**iter);
421 (*iter)->SetOffset(ret);
422 return ret;
423}
424
425/// Base class for materialization of Variables and ValueObjects.
426///
427/// Subclasses specify how to obtain the Value which is to be
428/// materialized.
430public:
431 virtual ~EntityVariableBase() = default;
432
434 // Hard-coding to maximum size of a pointer since all variables are
435 // materialized by reference
437 m_alignment = g_default_var_alignment;
438 }
439
441 lldb::addr_t process_address, Status &err) override {
442 Log *log = GetLog(LLDBLog::Expressions);
443
444 const lldb::addr_t load_addr = process_address + m_offset;
445 if (log) {
446 LLDB_LOGF(log,
447 "EntityVariable::Materialize [address = 0x%" PRIx64
448 ", m_variable_sp = %s]",
449 (uint64_t)load_addr, GetName().GetCString());
450 }
451
452 ExecutionContextScope *scope = frame_sp.get();
453
454 if (!scope)
455 scope = map.GetBestExecutionContextScope();
456
457 lldb::ValueObjectSP valobj_sp = SetupValueObject(scope);
458
459 if (!valobj_sp) {
461 "couldn't get a value object for variable %s", GetName().AsCString());
462 return;
463 }
464
465 Status valobj_error = valobj_sp->GetError().Clone();
466
467 if (valobj_error.Fail()) {
469 "couldn't get the value of variable %s: %s", GetName().AsCString(),
470 valobj_error.AsCString());
471 return;
472 }
473
474 if (m_is_reference) {
475 DataExtractor valobj_extractor;
476 Status extract_error;
477 valobj_sp->GetData(valobj_extractor, extract_error);
478
479 if (!extract_error.Success()) {
481 "couldn't read contents of reference variable %s: %s",
482 GetName().AsCString(), extract_error.AsCString());
483 return;
484 }
485
486 lldb::offset_t offset = 0;
487 lldb::addr_t reference_addr = valobj_extractor.GetAddress(&offset);
488
489 Status write_error;
490 map.WritePointerToMemory(load_addr, reference_addr, write_error);
491
492 if (!write_error.Success()) {
494 "couldn't write the contents of reference "
495 "variable %s to memory: %s",
496 GetName().AsCString(), write_error.AsCString());
497 return;
498 }
499 } else {
500 AddressType address_type = eAddressTypeInvalid;
501 const bool scalar_is_load_address = false;
502 lldb::addr_t addr_of_valobj =
503 valobj_sp->GetAddressOf(scalar_is_load_address, &address_type);
504 if (addr_of_valobj != LLDB_INVALID_ADDRESS) {
505 Status write_error;
506 map.WritePointerToMemory(load_addr, addr_of_valobj, write_error);
507
508 if (!write_error.Success()) {
510 "couldn't write the address of variable %s to memory: %s",
511 GetName().AsCString(), write_error.AsCString());
512 return;
513 }
514 } else {
515 DataExtractor data;
516 Status extract_error;
517 valobj_sp->GetData(data, extract_error);
518 if (!extract_error.Success()) {
520 "couldn't get the value of %s: %s", GetName().AsCString(),
521 extract_error.AsCString());
522 return;
523 }
524
525 if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
527 "trying to create a temporary region for %s but one exists",
528 GetName().AsCString());
529 return;
530 }
531
532 if (data.GetByteSize() < GetByteSize(scope)) {
533 if (data.GetByteSize() == 0 && !LocationExpressionIsValid()) {
535 "the variable '%s' has no location, "
536 "it may have been optimized out",
537 GetName().AsCString());
538 } else {
540 "size of variable %s (%" PRIu64
541 ") is larger than the ValueObject's size (%" PRIu64 ")",
542 GetName().AsCString(), GetByteSize(scope).value_or(0),
543 data.GetByteSize());
544 }
545 return;
546 }
547
548 std::optional<size_t> opt_bit_align = GetTypeBitAlign(scope);
549 if (!opt_bit_align) {
551 "can't get the type alignment for %s", GetName().AsCString());
552 return;
553 }
554
555 size_t byte_align = (*opt_bit_align + 7) / 8;
556
557 Status alloc_error;
558 const bool zero_memory = false;
559
560 m_temporary_allocation = map.Malloc(
561 data.GetByteSize(), byte_align,
562 lldb::ePermissionsReadable | lldb::ePermissionsWritable,
563 IRMemoryMap::eAllocationPolicyMirror, zero_memory, alloc_error);
564
565 m_temporary_allocation_size = data.GetByteSize();
566
567 m_original_data = std::make_shared<DataBufferHeap>(data.GetDataStart(),
568 data.GetByteSize());
569
570 if (!alloc_error.Success()) {
572 "couldn't allocate a temporary region for %s: %s",
573 GetName().AsCString(), alloc_error.AsCString());
574 return;
575 }
576
577 Status write_error;
578
579 map.WriteMemory(m_temporary_allocation, data.GetDataStart(),
580 data.GetByteSize(), write_error);
581
582 if (!write_error.Success()) {
584 "couldn't write to the temporary region for %s: %s",
585 GetName().AsCString(), write_error.AsCString());
586 return;
587 }
588
589 Status pointer_write_error;
590
591 map.WritePointerToMemory(load_addr, m_temporary_allocation,
592 pointer_write_error);
593
594 if (!pointer_write_error.Success()) {
596 "couldn't write the address of the temporary region for %s: %s",
597 GetName().AsCString(), pointer_write_error.AsCString());
598 }
599 }
600 }
601 }
602
604 lldb::addr_t process_address, lldb::addr_t frame_top,
605 lldb::addr_t frame_bottom, Status &err) override {
606 Log *log = GetLog(LLDBLog::Expressions);
607
608 const lldb::addr_t load_addr = process_address + m_offset;
609 if (log) {
610 LLDB_LOGF(log,
611 "EntityVariable::Dematerialize [address = 0x%" PRIx64
612 ", m_variable_sp = %s]",
613 (uint64_t)load_addr, GetName().AsCString());
614 }
615
616 if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
617 ExecutionContextScope *scope = frame_sp.get();
618
619 if (!scope)
620 scope = map.GetBestExecutionContextScope();
621
622 lldb::ValueObjectSP valobj_sp = SetupValueObject(scope);
623
624 if (!valobj_sp) {
626 "couldn't get a value object for variable %s",
627 GetName().AsCString());
628 return;
629 }
630
632
633 Status extract_error;
634
635 map.GetMemoryData(data, m_temporary_allocation,
636 valobj_sp->GetByteSize().value_or(0), extract_error);
637
638 if (!extract_error.Success()) {
640 "couldn't get the data for variable %s", GetName().AsCString());
641 return;
642 }
643
644 bool actually_write = true;
645
646 if (m_original_data) {
647 if ((data.GetByteSize() == m_original_data->GetByteSize()) &&
648 !memcmp(m_original_data->GetBytes(), data.GetDataStart(),
649 data.GetByteSize())) {
650 actually_write = false;
651 }
652 }
653
654 Status set_error;
655
656 if (actually_write) {
657 valobj_sp->SetData(data, set_error);
658
659 if (!set_error.Success()) {
661 "couldn't write the new contents of %s back into the variable",
662 GetName().AsCString());
663 return;
664 }
665 }
666
667 Status free_error;
668
669 map.Free(m_temporary_allocation, free_error);
670
671 if (!free_error.Success()) {
673 "couldn't free the temporary region for %s: %s",
674 GetName().AsCString(), free_error.AsCString());
675 return;
676 }
677
678 m_original_data.reset();
679 m_temporary_allocation = LLDB_INVALID_ADDRESS;
680 m_temporary_allocation_size = 0;
681 }
682 }
683
684 void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
685 Log *log) override {
686 StreamString dump_stream;
687
688 const lldb::addr_t load_addr = process_address + m_offset;
689 dump_stream.Printf("0x%" PRIx64 ": EntityVariable\n", load_addr);
690
691 Status err;
692
694
695 {
696 dump_stream.Printf("Pointer:\n");
697
698 DataBufferHeap data(m_size, 0);
699
700 map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
701
702 if (!err.Success()) {
703 dump_stream.Printf(" <could not be read>\n");
704 } else {
705 DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
706 map.GetByteOrder(), map.GetAddressByteSize());
707
708 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
709 load_addr);
710
711 lldb::offset_t offset = 0;
712
713 ptr = extractor.GetAddress(&offset);
714
715 dump_stream.PutChar('\n');
716 }
717 }
718
719 if (m_temporary_allocation == LLDB_INVALID_ADDRESS) {
720 dump_stream.Printf("Points to process memory:\n");
721 } else {
722 dump_stream.Printf("Temporary allocation:\n");
723 }
724
725 if (ptr == LLDB_INVALID_ADDRESS) {
726 dump_stream.Printf(" <could not be be found>\n");
727 } else {
728 DataBufferHeap data(m_temporary_allocation_size, 0);
729
730 map.ReadMemory(data.GetBytes(), m_temporary_allocation,
731 m_temporary_allocation_size, err);
732
733 if (!err.Success()) {
734 dump_stream.Printf(" <could not be read>\n");
735 } else {
736 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
737 load_addr);
738
739 dump_stream.PutChar('\n');
740 }
741 }
742
743 log->PutString(dump_stream.GetString());
744 }
745
746 void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {
747 if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
748 Status free_error;
749
750 map.Free(m_temporary_allocation, free_error);
751
752 m_temporary_allocation = LLDB_INVALID_ADDRESS;
753 m_temporary_allocation_size = 0;
754 }
755 }
756
757private:
758 virtual ConstString GetName() const = 0;
759
760 /// Creates and returns ValueObject tied to this variable
761 /// and prepares Entity for materialization.
762 ///
763 /// Called each time the Materializer (de)materializes a
764 /// variable. We re-create the ValueObject based on the
765 /// current ExecutionContextScope since clients such as
766 /// conditional breakpoints may materialize the same
767 /// EntityVariable multiple times with different frames.
768 ///
769 /// Each subsequent use of the EntityVariableBase interface
770 /// will query the newly created ValueObject until this
771 /// function is called again.
772 virtual lldb::ValueObjectSP
774
775 /// Returns size in bytes of the type associated with this variable
776 ///
777 /// \returns On success, returns byte size of the type associated
778 /// with this variable. Returns std::nullopt otherwise.
779 virtual std::optional<uint64_t>
781
782 /// Returns 'true' if the location expression associated with this variable
783 /// is valid.
784 virtual bool LocationExpressionIsValid() const = 0;
785
786 /// Returns alignment of the type associated with this variable in bits.
787 ///
788 /// \returns On success, returns alignment in bits for the type associated
789 /// with this variable. Returns std::nullopt otherwise.
790 virtual std::optional<size_t>
792
793protected:
794 bool m_is_reference = false;
795 lldb::addr_t m_temporary_allocation = LLDB_INVALID_ADDRESS;
796 size_t m_temporary_allocation_size = 0;
798};
799
800/// Represents an Entity constructed from a VariableSP.
801///
802/// This class is used for materialization of variables for which
803/// the user has a VariableSP on hand. The ValueObject is then
804/// derived from the associated DWARF location expression when needed
805/// by the Materializer.
807public:
808 EntityVariable(lldb::VariableSP &variable_sp) : m_variable_sp(variable_sp) {
809 m_is_reference =
810 m_variable_sp->GetType()->GetForwardCompilerType().IsReferenceType();
811 }
812
813 ConstString GetName() const override { return m_variable_sp->GetName(); }
814
816 assert(m_variable_sp != nullptr);
817 return ValueObjectVariable::Create(scope, m_variable_sp);
818 }
819
820 std::optional<uint64_t>
821 GetByteSize(ExecutionContextScope *scope) const override {
822 return m_variable_sp->GetType()->GetByteSize(scope);
823 }
824
825 bool LocationExpressionIsValid() const override {
826 return m_variable_sp->LocationExpressionList().IsValid();
827 }
828
829 std::optional<size_t>
830 GetTypeBitAlign(ExecutionContextScope *scope) const override {
831 return m_variable_sp->GetType()->GetLayoutCompilerType().GetTypeBitAlign(
832 scope);
833 }
834
835private:
836 lldb::VariableSP m_variable_sp; ///< Variable that this entity is based on.
837};
838
839/// Represents an Entity constructed from a VariableSP.
840///
841/// This class is used for materialization of variables for
842/// which the user does not have a VariableSP available (e.g.,
843/// when materializing ivars).
845public:
847 : m_name(name), m_valobj_provider(std::move(provider)) {
848 assert(m_valobj_provider);
849 }
850
851 ConstString GetName() const override { return m_name; }
852
854 m_valobj_sp =
855 m_valobj_provider(GetName(), scope->CalculateStackFrame().get());
856
857 if (m_valobj_sp)
858 m_is_reference = m_valobj_sp->GetCompilerType().IsReferenceType();
859
860 return m_valobj_sp;
861 }
862
863 std::optional<uint64_t>
864 GetByteSize(ExecutionContextScope *scope) const override {
865 if (m_valobj_sp)
866 return m_valobj_sp->GetCompilerType().GetByteSize(scope);
867
868 return {};
869 }
870
871 bool LocationExpressionIsValid() const override {
872 if (m_valobj_sp)
873 return m_valobj_sp->GetError().Success();
874
875 return false;
876 }
877
878 std::optional<size_t>
879 GetTypeBitAlign(ExecutionContextScope *scope) const override {
880 if (m_valobj_sp)
881 return m_valobj_sp->GetCompilerType().GetTypeBitAlign(scope);
882
883 return {};
884 }
885
886private:
890};
891
893 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
894 *iter = std::make_unique<EntityVariable>(variable_sp);
895 uint32_t ret = AddStructMember(**iter);
896 (*iter)->SetOffset(ret);
897 return ret;
898}
899
901 ValueObjectProviderTy valobj_provider,
902 Status &err) {
903 assert(valobj_provider);
904 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
905 *iter = std::make_unique<EntityValueObject>(name, std::move(valobj_provider));
906 uint32_t ret = AddStructMember(**iter);
907 (*iter)->SetOffset(ret);
908 return ret;
909}
910
912public:
913 EntityResultVariable(const CompilerType &type, bool is_program_reference,
914 bool keep_in_memory,
916 : Entity(), m_type(type), m_is_program_reference(is_program_reference),
917 m_keep_in_memory(keep_in_memory), m_delegate(delegate) {
918 // Hard-coding to maximum size of a pointer since all results are
919 // materialized by reference
921 m_alignment = g_default_var_alignment;
922 }
923
925 lldb::addr_t process_address, Status &err) override {
926 if (!m_is_program_reference) {
927 if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
929 "Trying to create a temporary region for the result "
930 "but one exists");
931 return;
932 }
933
934 const lldb::addr_t load_addr = process_address + m_offset;
935
936 ExecutionContextScope *exe_scope = frame_sp.get();
937 if (!exe_scope)
938 exe_scope = map.GetBestExecutionContextScope();
939
940 std::optional<uint64_t> byte_size = m_type.GetByteSize(exe_scope);
941 if (!byte_size) {
943 "can't get size of type \"%s\"", m_type.GetTypeName().AsCString());
944 return;
945 }
946
947 std::optional<size_t> opt_bit_align = m_type.GetTypeBitAlign(exe_scope);
948 if (!opt_bit_align) {
950 "can't get the alignment of type \"%s\"",
951 m_type.GetTypeName().AsCString());
952 return;
953 }
954
955 size_t byte_align = (*opt_bit_align + 7) / 8;
956
957 Status alloc_error;
958 const bool zero_memory = true;
959
960 m_temporary_allocation = map.Malloc(
961 *byte_size, byte_align,
962 lldb::ePermissionsReadable | lldb::ePermissionsWritable,
963 IRMemoryMap::eAllocationPolicyMirror, zero_memory, alloc_error);
964 m_temporary_allocation_size = *byte_size;
965
966 if (!alloc_error.Success()) {
968 "couldn't allocate a temporary region for the result: %s",
969 alloc_error.AsCString());
970 return;
971 }
972
973 Status pointer_write_error;
974
975 map.WritePointerToMemory(load_addr, m_temporary_allocation,
976 pointer_write_error);
977
978 if (!pointer_write_error.Success()) {
980 "couldn't write the address of the "
981 "temporary region for the result: %s",
982 pointer_write_error.AsCString());
983 }
984 }
985 }
986
988 lldb::addr_t process_address, lldb::addr_t frame_top,
989 lldb::addr_t frame_bottom, Status &err) override {
990 err.Clear();
991
992 ExecutionContextScope *exe_scope = frame_sp.get();
993 if (!exe_scope)
994 exe_scope = map.GetBestExecutionContextScope();
995
996 if (!exe_scope) {
998 "Couldn't dematerialize a result variable: invalid "
999 "execution context scope");
1000 return;
1001 }
1002
1003 lldb::addr_t address;
1004 Status read_error;
1005 const lldb::addr_t load_addr = process_address + m_offset;
1006
1007 map.ReadPointerFromMemory(&address, load_addr, read_error);
1008
1009 if (!read_error.Success()) {
1011 "Couldn't dematerialize a result variable: couldn't "
1012 "read its address");
1013 return;
1014 }
1015
1016 lldb::TargetSP target_sp = exe_scope->CalculateTarget();
1017
1018 if (!target_sp) {
1020 "Couldn't dematerialize a result variable: no target");
1021 return;
1022 }
1023
1024 auto type_system_or_err =
1025 target_sp->GetScratchTypeSystemForLanguage(m_type.GetMinimumLanguage());
1026
1027 if (auto error = type_system_or_err.takeError()) {
1029 "Couldn't dematerialize a result variable: "
1030 "couldn't get the corresponding type "
1031 "system: %s",
1032 llvm::toString(std::move(error)).c_str());
1033 return;
1034 }
1035 auto ts = *type_system_or_err;
1036 if (!ts) {
1038 "Couldn't dematerialize a result variable: "
1039 "couldn't corresponding type system is "
1040 "no longer live.");
1041 return;
1042 }
1043 PersistentExpressionState *persistent_state =
1044 ts->GetPersistentExpressionState();
1045
1046 if (!persistent_state) {
1048 "Couldn't dematerialize a result variable: "
1049 "corresponding type system doesn't handle persistent "
1050 "variables");
1051 return;
1052 }
1053
1054 ConstString name = m_delegate
1055 ? m_delegate->GetName()
1056 : persistent_state->GetNextPersistentVariableName();
1057
1059 exe_scope, name, m_type, map.GetByteOrder(), map.GetAddressByteSize());
1060
1061 if (!ret) {
1063 "couldn't dematerialize a result variable: "
1064 "failed to make persistent variable %s",
1065 name.AsCString());
1066 return;
1067 }
1068
1069 lldb::ProcessSP process_sp =
1071
1072 if (m_delegate) {
1073 m_delegate->DidDematerialize(ret);
1074 }
1075
1076 bool can_persist =
1077 (m_is_program_reference && process_sp && process_sp->CanJIT() &&
1078 !(address >= frame_bottom && address < frame_top));
1079
1080 if (can_persist && m_keep_in_memory) {
1081 ret->m_live_sp = ValueObjectConstResult::Create(exe_scope, m_type, name,
1082 address, eAddressTypeLoad,
1083 map.GetAddressByteSize());
1084 }
1085
1086 ret->ValueUpdated();
1087
1088 const size_t pvar_byte_size = ret->GetByteSize().value_or(0);
1089 uint8_t *pvar_data = ret->GetValueBytes();
1090
1091 map.ReadMemory(pvar_data, address, pvar_byte_size, read_error);
1092
1093 if (!read_error.Success()) {
1095 "Couldn't dematerialize a result variable: couldn't read its memory");
1096 return;
1097 }
1098
1099 if (!can_persist || !m_keep_in_memory) {
1101
1102 if (m_temporary_allocation != LLDB_INVALID_ADDRESS) {
1103 Status free_error;
1104 map.Free(m_temporary_allocation, free_error);
1105 }
1106 } else {
1108 }
1109
1110 m_temporary_allocation = LLDB_INVALID_ADDRESS;
1111 m_temporary_allocation_size = 0;
1112 }
1113
1114 void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
1115 Log *log) override {
1116 StreamString dump_stream;
1117
1118 const lldb::addr_t load_addr = process_address + m_offset;
1119
1120 dump_stream.Printf("0x%" PRIx64 ": EntityResultVariable\n", load_addr);
1121
1122 Status err;
1123
1125
1126 {
1127 dump_stream.Printf("Pointer:\n");
1128
1129 DataBufferHeap data(m_size, 0);
1130
1131 map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
1132
1133 if (!err.Success()) {
1134 dump_stream.Printf(" <could not be read>\n");
1135 } else {
1136 DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
1137 map.GetByteOrder(), map.GetAddressByteSize());
1138
1139 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
1140 load_addr);
1141
1142 lldb::offset_t offset = 0;
1143
1144 ptr = extractor.GetAddress(&offset);
1145
1146 dump_stream.PutChar('\n');
1147 }
1148 }
1149
1150 if (m_temporary_allocation == LLDB_INVALID_ADDRESS) {
1151 dump_stream.Printf("Points to process memory:\n");
1152 } else {
1153 dump_stream.Printf("Temporary allocation:\n");
1154 }
1155
1156 if (ptr == LLDB_INVALID_ADDRESS) {
1157 dump_stream.Printf(" <could not be be found>\n");
1158 } else {
1159 DataBufferHeap data(m_temporary_allocation_size, 0);
1160
1161 map.ReadMemory(data.GetBytes(), m_temporary_allocation,
1162 m_temporary_allocation_size, err);
1163
1164 if (!err.Success()) {
1165 dump_stream.Printf(" <could not be read>\n");
1166 } else {
1167 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
1168 load_addr);
1169
1170 dump_stream.PutChar('\n');
1171 }
1172 }
1173
1174 log->PutString(dump_stream.GetString());
1175 }
1176
1177 void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {
1178 if (!m_keep_in_memory && m_temporary_allocation != LLDB_INVALID_ADDRESS) {
1179 Status free_error;
1180
1181 map.Free(m_temporary_allocation, free_error);
1182 }
1183
1184 m_temporary_allocation = LLDB_INVALID_ADDRESS;
1185 m_temporary_allocation_size = 0;
1186 }
1187
1188private:
1192
1193 lldb::addr_t m_temporary_allocation = LLDB_INVALID_ADDRESS;
1194 size_t m_temporary_allocation_size = 0;
1196};
1197
1199 bool is_program_reference,
1200 bool keep_in_memory,
1202 Status &err) {
1203 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1204 *iter = std::make_unique<EntityResultVariable>(type, is_program_reference,
1205 keep_in_memory, delegate);
1206 uint32_t ret = AddStructMember(**iter);
1207 (*iter)->SetOffset(ret);
1208 return ret;
1209}
1210
1212public:
1213 EntitySymbol(const Symbol &symbol) : Entity(), m_symbol(symbol) {
1214 // Hard-coding to maximum size of a symbol
1215 m_size = g_default_var_byte_size;
1216 m_alignment = g_default_var_alignment;
1217 }
1218
1220 lldb::addr_t process_address, Status &err) override {
1221 Log *log = GetLog(LLDBLog::Expressions);
1222
1223 const lldb::addr_t load_addr = process_address + m_offset;
1224
1225 if (log) {
1226 LLDB_LOGF(log,
1227 "EntitySymbol::Materialize [address = 0x%" PRIx64
1228 ", m_symbol = %s]",
1229 (uint64_t)load_addr, m_symbol.GetName().AsCString());
1230 }
1231
1232 const Address sym_address = m_symbol.GetAddress();
1233
1234 ExecutionContextScope *exe_scope = frame_sp.get();
1235 if (!exe_scope)
1236 exe_scope = map.GetBestExecutionContextScope();
1237
1238 lldb::TargetSP target_sp;
1239
1240 if (exe_scope)
1241 target_sp = map.GetBestExecutionContextScope()->CalculateTarget();
1242
1243 if (!target_sp) {
1245 "couldn't resolve symbol %s because there is no target",
1246 m_symbol.GetName().AsCString());
1247 return;
1248 }
1249
1250 lldb::addr_t resolved_address = sym_address.GetLoadAddress(target_sp.get());
1251
1252 if (resolved_address == LLDB_INVALID_ADDRESS)
1253 resolved_address = sym_address.GetFileAddress();
1254
1255 Status pointer_write_error;
1256
1257 map.WritePointerToMemory(load_addr, resolved_address, pointer_write_error);
1258
1259 if (!pointer_write_error.Success()) {
1261 "couldn't write the address of symbol %s: %s",
1262 m_symbol.GetName().AsCString(), pointer_write_error.AsCString());
1263 return;
1264 }
1265 }
1266
1268 lldb::addr_t process_address, lldb::addr_t frame_top,
1269 lldb::addr_t frame_bottom, Status &err) override {
1270 Log *log = GetLog(LLDBLog::Expressions);
1271
1272 const lldb::addr_t load_addr = process_address + m_offset;
1273
1274 if (log) {
1275 LLDB_LOGF(log,
1276 "EntitySymbol::Dematerialize [address = 0x%" PRIx64
1277 ", m_symbol = %s]",
1278 (uint64_t)load_addr, m_symbol.GetName().AsCString());
1279 }
1280
1281 // no work needs to be done
1282 }
1283
1284 void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
1285 Log *log) override {
1286 StreamString dump_stream;
1287
1288 Status err;
1289
1290 const lldb::addr_t load_addr = process_address + m_offset;
1291
1292 dump_stream.Printf("0x%" PRIx64 ": EntitySymbol (%s)\n", load_addr,
1293 m_symbol.GetName().AsCString());
1294
1295 {
1296 dump_stream.Printf("Pointer:\n");
1297
1298 DataBufferHeap data(m_size, 0);
1299
1300 map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
1301
1302 if (!err.Success()) {
1303 dump_stream.Printf(" <could not be read>\n");
1304 } else {
1305 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
1306 load_addr);
1307
1308 dump_stream.PutChar('\n');
1309 }
1310 }
1311
1312 log->PutString(dump_stream.GetString());
1313 }
1314
1315 void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}
1316
1317private:
1319};
1320
1321uint32_t Materializer::AddSymbol(const Symbol &symbol_sp, Status &err) {
1322 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1323 *iter = std::make_unique<EntitySymbol>(symbol_sp);
1324 uint32_t ret = AddStructMember(**iter);
1325 (*iter)->SetOffset(ret);
1326 return ret;
1327}
1328
1330public:
1331 EntityRegister(const RegisterInfo &register_info)
1332 : Entity(), m_register_info(register_info) {
1333 // Hard-coding alignment conservatively
1334 m_size = m_register_info.byte_size;
1335 m_alignment = m_register_info.byte_size;
1336 }
1337
1339 lldb::addr_t process_address, Status &err) override {
1340 Log *log = GetLog(LLDBLog::Expressions);
1341
1342 const lldb::addr_t load_addr = process_address + m_offset;
1343
1344 if (log) {
1345 LLDB_LOGF(log,
1346 "EntityRegister::Materialize [address = 0x%" PRIx64
1347 ", m_register_info = %s]",
1348 (uint64_t)load_addr, m_register_info.name);
1349 }
1350
1351 RegisterValue reg_value;
1352
1353 if (!frame_sp.get()) {
1355 "couldn't materialize register %s without a stack frame",
1356 m_register_info.name);
1357 return;
1358 }
1359
1360 lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
1361
1362 if (!reg_context_sp->ReadRegister(&m_register_info, reg_value)) {
1364 "couldn't read the value of register %s", m_register_info.name);
1365 return;
1366 }
1367
1368 DataExtractor register_data;
1369
1370 if (!reg_value.GetData(register_data)) {
1372 "couldn't get the data for register %s", m_register_info.name);
1373 return;
1374 }
1375
1376 if (register_data.GetByteSize() != m_register_info.byte_size) {
1378 "data for register %s had size %llu but we expected %llu",
1379 m_register_info.name, (unsigned long long)register_data.GetByteSize(),
1380 (unsigned long long)m_register_info.byte_size);
1381 return;
1382 }
1383
1384 m_register_contents = std::make_shared<DataBufferHeap>(
1385 register_data.GetDataStart(), register_data.GetByteSize());
1386
1387 Status write_error;
1388
1389 map.WriteMemory(load_addr, register_data.GetDataStart(),
1390 register_data.GetByteSize(), write_error);
1391
1392 if (!write_error.Success()) {
1394 "couldn't write the contents of register %s: %s",
1395 m_register_info.name, write_error.AsCString());
1396 return;
1397 }
1398 }
1399
1401 lldb::addr_t process_address, lldb::addr_t frame_top,
1402 lldb::addr_t frame_bottom, Status &err) override {
1403 Log *log = GetLog(LLDBLog::Expressions);
1404
1405 const lldb::addr_t load_addr = process_address + m_offset;
1406
1407 if (log) {
1408 LLDB_LOGF(log,
1409 "EntityRegister::Dematerialize [address = 0x%" PRIx64
1410 ", m_register_info = %s]",
1411 (uint64_t)load_addr, m_register_info.name);
1412 }
1413
1414 Status extract_error;
1415
1416 DataExtractor register_data;
1417
1418 if (!frame_sp.get()) {
1420 "couldn't dematerialize register %s without a stack frame",
1421 m_register_info.name);
1422 return;
1423 }
1424
1425 lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
1426
1427 map.GetMemoryData(register_data, load_addr, m_register_info.byte_size,
1428 extract_error);
1429
1430 if (!extract_error.Success()) {
1432 "couldn't get the data for register %s: %s", m_register_info.name,
1433 extract_error.AsCString());
1434 return;
1435 }
1436
1437 if (!memcmp(register_data.GetDataStart(), m_register_contents->GetBytes(),
1438 register_data.GetByteSize())) {
1439 // No write required, and in particular we avoid errors if the register
1440 // wasn't writable
1441
1442 m_register_contents.reset();
1443 return;
1444 }
1445
1446 m_register_contents.reset();
1447
1448 RegisterValue register_value(register_data.GetData(),
1449 register_data.GetByteOrder());
1450
1451 if (!reg_context_sp->WriteRegister(&m_register_info, register_value)) {
1453 "couldn't write the value of register %s", m_register_info.name);
1454 return;
1455 }
1456 }
1457
1458 void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
1459 Log *log) override {
1460 StreamString dump_stream;
1461
1462 Status err;
1463
1464 const lldb::addr_t load_addr = process_address + m_offset;
1465
1466 dump_stream.Printf("0x%" PRIx64 ": EntityRegister (%s)\n", load_addr,
1467 m_register_info.name);
1468
1469 {
1470 dump_stream.Printf("Value:\n");
1471
1472 DataBufferHeap data(m_size, 0);
1473
1474 map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
1475
1476 if (!err.Success()) {
1477 dump_stream.Printf(" <could not be read>\n");
1478 } else {
1479 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
1480 load_addr);
1481
1482 dump_stream.PutChar('\n');
1483 }
1484 }
1485
1486 log->PutString(dump_stream.GetString());
1487 }
1488
1489 void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}
1490
1491private:
1494};
1495
1496uint32_t Materializer::AddRegister(const RegisterInfo &register_info,
1497 Status &err) {
1498 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1499 *iter = std::make_unique<EntityRegister>(register_info);
1500 uint32_t ret = AddStructMember(**iter);
1501 (*iter)->SetOffset(ret);
1502 return ret;
1503}
1504
1506 DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
1507
1508 if (dematerializer_sp)
1509 dematerializer_sp->Wipe();
1510}
1511
1514 lldb::addr_t process_address, Status &error) {
1515 ExecutionContextScope *exe_scope = frame_sp.get();
1516 if (!exe_scope)
1517 exe_scope = map.GetBestExecutionContextScope();
1518
1519 DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
1520
1521 if (dematerializer_sp) {
1522 error =
1523 Status::FromErrorString("Couldn't materialize: already materialized");
1524 }
1525
1526 DematerializerSP ret(
1527 new Dematerializer(*this, frame_sp, map, process_address));
1528
1529 if (!exe_scope) {
1530 error =
1531 Status::FromErrorString("Couldn't materialize: target doesn't exist");
1532 }
1533
1534 for (EntityUP &entity_up : m_entities) {
1535 entity_up->Materialize(frame_sp, map, process_address, error);
1536
1537 if (!error.Success())
1538 return DematerializerSP();
1539 }
1540
1541 if (Log *log = GetLog(LLDBLog::Expressions)) {
1542 LLDB_LOGF(
1543 log,
1544 "Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64
1545 ") materialized:",
1546 static_cast<void *>(frame_sp.get()), process_address);
1547 for (EntityUP &entity_up : m_entities)
1548 entity_up->DumpToLog(map, process_address, log);
1549 }
1550
1551 m_dematerializer_wp = ret;
1552
1553 return ret;
1554}
1555
1557 lldb::addr_t frame_bottom,
1558 lldb::addr_t frame_top) {
1559 lldb::StackFrameSP frame_sp;
1560
1561 lldb::ThreadSP thread_sp = m_thread_wp.lock();
1562 if (thread_sp)
1563 frame_sp = thread_sp->GetFrameWithStackID(m_stack_id);
1564
1565 ExecutionContextScope *exe_scope = frame_sp.get();
1566 if (!exe_scope)
1567 exe_scope = m_map->GetBestExecutionContextScope();
1568
1569 if (!IsValid()) {
1571 "Couldn't dematerialize: invalid dematerializer");
1572 }
1573
1574 if (!exe_scope) {
1575 error = Status::FromErrorString("Couldn't dematerialize: target is gone");
1576 } else {
1577 if (Log *log = GetLog(LLDBLog::Expressions)) {
1578 LLDB_LOGF(log,
1579 "Materializer::Dematerialize (frame_sp = %p, process_address "
1580 "= 0x%" PRIx64 ") about to dematerialize:",
1581 static_cast<void *>(frame_sp.get()), m_process_address);
1582 for (EntityUP &entity_up : m_materializer->m_entities)
1583 entity_up->DumpToLog(*m_map, m_process_address, log);
1584 }
1585
1586 for (EntityUP &entity_up : m_materializer->m_entities) {
1587 entity_up->Dematerialize(frame_sp, *m_map, m_process_address, frame_top,
1588 frame_bottom, error);
1589
1590 if (!error.Success())
1591 break;
1592 }
1593 }
1594
1595 Wipe();
1596}
1597
1599 if (!IsValid())
1600 return;
1601
1602 for (EntityUP &entity_up : m_materializer->m_entities) {
1603 entity_up->Wipe(*m_map, m_process_address);
1604 }
1605
1606 m_materializer = nullptr;
1607 m_map = nullptr;
1608 m_process_address = LLDB_INVALID_ADDRESS;
1609}
1610
1612 default;
1614 default;
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOGF(log,...)
Definition: Log.h:376
static constexpr uint32_t g_default_var_byte_size
static constexpr uint32_t g_default_var_alignment
static llvm::StringRef GetName(XcodeSDK::Type type)
Definition: XcodeSDK.cpp:21
Materializer::PersistentVariableDelegate * m_delegate
lldb::ExpressionVariableSP m_persistent_variable_sp
void DestroyAllocation(IRMemoryMap &map, Status &err)
void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Status &err) override
void MakeAllocation(IRMemoryMap &map, Status &err)
void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, lldb::addr_t frame_top, lldb::addr_t frame_bottom, Status &err) override
void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override
EntityPersistentVariable(lldb::ExpressionVariableSP &persistent_variable_sp, Materializer::PersistentVariableDelegate *delegate)
void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Status &err) override
void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override
void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, lldb::addr_t frame_top, lldb::addr_t frame_bottom, Status &err) override
RegisterInfo m_register_info
void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
lldb::DataBufferSP m_register_contents
EntityRegister(const RegisterInfo &register_info)
void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, lldb::addr_t frame_top, lldb::addr_t frame_bottom, Status &err) override
void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override
Materializer::PersistentVariableDelegate * m_delegate
EntityResultVariable(const CompilerType &type, bool is_program_reference, bool keep_in_memory, Materializer::PersistentVariableDelegate *delegate)
void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Status &err) override
void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
EntitySymbol(const Symbol &symbol)
void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override
void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Status &err) override
void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, lldb::addr_t frame_top, lldb::addr_t frame_bottom, Status &err) override
Represents an Entity constructed from a VariableSP.
ConstString GetName() const override
ValueObjectProviderTy m_valobj_provider
lldb::ValueObjectSP m_valobj_sp
bool LocationExpressionIsValid() const override
Returns 'true' if the location expression associated with this variable is valid.
std::optional< size_t > GetTypeBitAlign(ExecutionContextScope *scope) const override
Returns alignment of the type associated with this variable in bits.
lldb::ValueObjectSP SetupValueObject(ExecutionContextScope *scope) override
Creates and returns ValueObject tied to this variable and prepares Entity for materialization.
std::optional< uint64_t > GetByteSize(ExecutionContextScope *scope) const override
Returns size in bytes of the type associated with this variable.
ConstString m_name
EntityValueObject(ConstString name, ValueObjectProviderTy provider)
Base class for materialization of Variables and ValueObjects.
lldb::DataBufferSP m_original_data
void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Status &err) override
virtual std::optional< uint64_t > GetByteSize(ExecutionContextScope *scope) const =0
Returns size in bytes of the type associated with this variable.
virtual ~EntityVariableBase()=default
void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override
void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override
virtual std::optional< size_t > GetTypeBitAlign(ExecutionContextScope *scope) const =0
Returns alignment of the type associated with this variable in bits.
virtual ConstString GetName() const =0
virtual bool LocationExpressionIsValid() const =0
Returns 'true' if the location expression associated with this variable is valid.
virtual lldb::ValueObjectSP SetupValueObject(ExecutionContextScope *scope)=0
Creates and returns ValueObject tied to this variable and prepares Entity for materialization.
void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, lldb::addr_t frame_top, lldb::addr_t frame_bottom, Status &err) override
Represents an Entity constructed from a VariableSP.
ConstString GetName() const override
std::optional< size_t > GetTypeBitAlign(ExecutionContextScope *scope) const override
Returns alignment of the type associated with this variable in bits.
lldb::ValueObjectSP SetupValueObject(ExecutionContextScope *scope) override
Creates and returns ValueObject tied to this variable and prepares Entity for materialization.
bool LocationExpressionIsValid() const override
Returns 'true' if the location expression associated with this variable is valid.
lldb::VariableSP m_variable_sp
Variable that this entity is based on.
std::optional< uint64_t > GetByteSize(ExecutionContextScope *scope) const override
Returns size in bytes of the type associated with this variable.
EntityVariable(lldb::VariableSP &variable_sp)
A section + offset based address class.
Definition: Address.h:62
lldb::addr_t GetLoadAddress(Target *target) const
Get the load address.
Definition: Address.cpp:313
lldb::addr_t GetFileAddress() const
Get the file address.
Definition: Address.cpp:293
Generic representation of a type in a programming language.
Definition: CompilerType.h:36
A uniqued constant string class.
Definition: ConstString.h:40
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
Definition: ConstString.h:188
A subclass of DataBuffer that stores a data buffer on the heap.
lldb::offset_t GetByteSize() const override
Get the number of bytes in the data buffer.
An data extractor class.
Definition: DataExtractor.h:48
const void * GetData(lldb::offset_t *offset_ptr, lldb::offset_t length) const
Extract length bytes from *offset_ptr.
uint64_t GetByteSize() const
Get the number of bytes contained in this object.
uint64_t GetAddress(lldb::offset_t *offset_ptr) const
Extract an address from *offset_ptr.
const uint8_t * GetDataStart() const
Get the data start pointer.
lldb::ByteOrder GetByteOrder() const
Get the current byte order value.
"lldb/Target/ExecutionContextScope.h" Inherit from this if your object can reconstruct its execution ...
virtual lldb::StackFrameSP CalculateStackFrame()=0
virtual lldb::ProcessSP CalculateProcess()=0
virtual lldb::TargetSP CalculateTarget()=0
@ EVIsLLDBAllocated
This variable is resident in a location specifically allocated for it by LLDB in the target process.
@ EVNeedsFreezeDry
Copy from m_live_sp to m_frozen_sp during dematerialization.
@ EVNeedsAllocation
Space for this variable has yet to be allocated in the target process.
@ EVIsProgramReference
This variable is a reference to a (possibly invalid) area managed by the target program.
@ EVKeepInTarget
Keep the allocation after the expression is complete rather than freeze drying its contents and freei...
Encapsulates memory that may exist in the process but must also be available in the host process.
Definition: IRMemoryMap.h:34
void Free(lldb::addr_t process_address, Status &error)
lldb::ByteOrder GetByteOrder()
void ReadPointerFromMemory(lldb::addr_t *address, lldb::addr_t process_address, Status &error)
ExecutionContextScope * GetBestExecutionContextScope() const
lldb::addr_t Malloc(size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, bool zero_memory, Status &error)
void GetMemoryData(DataExtractor &extractor, lldb::addr_t process_address, size_t size, Status &error)
void WritePointerToMemory(lldb::addr_t process_address, lldb::addr_t address, Status &error)
void WriteScalarToMemory(lldb::addr_t process_address, Scalar &scalar, size_t size, Status &error)
void Leak(lldb::addr_t process_address, Status &error)
void WriteMemory(lldb::addr_t process_address, const uint8_t *bytes, size_t size, Status &error)
void ReadMemory(uint8_t *bytes, lldb::addr_t process_address, size_t size, Status &error)
@ eAllocationPolicyMirror
The intent is that this allocation exist both in the host and the process and have the same content i...
Definition: IRMemoryMap.h:46
void PutString(llvm::StringRef str)
Definition: Log.cpp:147
void Dematerialize(Status &err, lldb::addr_t frame_top, lldb::addr_t frame_bottom)
uint32_t AddResultVariable(const CompilerType &type, bool is_lvalue, bool keep_in_memory, PersistentVariableDelegate *delegate, Status &err)
uint32_t AddStructMember(Entity &entity)
std::unique_ptr< Entity > EntityUP
Definition: Materializer.h:147
std::shared_ptr< Dematerializer > DematerializerSP
Definition: Materializer.h:64
DematerializerSP Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Status &err)
uint32_t AddSymbol(const Symbol &symbol_sp, Status &err)
uint32_t AddRegister(const RegisterInfo &register_info, Status &err)
DematerializerWP m_dematerializer_wp
Definition: Materializer.h:150
uint32_t AddValueObject(ConstString name, ValueObjectProviderTy valobj_provider, Status &err)
Create entity from supplied ValueObject and count it as a member of the materialized struct.
uint32_t AddPersistentVariable(lldb::ExpressionVariableSP &persistent_variable_sp, PersistentVariableDelegate *delegate, Status &err)
uint32_t AddVariable(lldb::VariableSP &variable_sp, Status &err)
virtual lldb::ExpressionVariableSP CreatePersistentVariable(const lldb::ValueObjectSP &valobj_sp)=0
virtual ConstString GetNextPersistentVariableName(bool is_error=false)=0
Return a new persistent variable name with the specified prefix.
bool GetData(DataExtractor &data) const
An error handling class.
Definition: Status.h:118
void Clear()
Clear the object state.
Definition: Status.cpp:215
ValueType GetError() const
Access the error value.
Definition: Status.cpp:222
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Definition: Status.cpp:106
static Status FromErrorString(const char *str)
Definition: Status.h:141
bool Fail() const
Test for error condition.
Definition: Status.cpp:294
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
Definition: Status.cpp:195
bool Success() const
Test for success condition.
Definition: Status.cpp:304
llvm::StringRef GetString() const
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:134
size_t PutChar(char ch)
Definition: Stream.cpp:131
static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size, lldb::addr_t address=LLDB_INVALID_ADDRESS)
static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp)
uint8_t * GetBytes()
Get a pointer to the data.
Definition: DataBuffer.h:108
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:82
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:332
void DumpHexBytes(Stream *s, const void *src, size_t src_len, uint32_t bytes_per_line, lldb::addr_t base_addr)
std::function< lldb::ValueObjectSP(ConstString, StackFrame *)> ValueObjectProviderTy
Functor that returns a ValueObjectSP for a variable given its name and the StackFrame of interest.
@ eAddressTypeLoad
Address is an address as in the current target inferior process.
std::shared_ptr< lldb_private::StackFrame > StackFrameSP
Definition: lldb-forward.h:424
std::shared_ptr< lldb_private::Thread > ThreadSP
Definition: lldb-forward.h:450
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
Definition: lldb-forward.h:484
std::shared_ptr< lldb_private::ExpressionVariable > ExpressionVariableSP
Definition: lldb-forward.h:351
uint64_t offset_t
Definition: lldb-types.h:85
std::shared_ptr< lldb_private::Process > ProcessSP
Definition: lldb-forward.h:389
std::shared_ptr< lldb_private::Variable > VariableSP
Definition: lldb-forward.h:486
std::shared_ptr< lldb_private::DataBuffer > DataBufferSP
Definition: lldb-forward.h:336
uint64_t addr_t
Definition: lldb-types.h:80
std::shared_ptr< lldb_private::Target > TargetSP
Definition: lldb-forward.h:448
std::shared_ptr< lldb_private::RegisterContext > RegisterContextSP
Definition: lldb-forward.h:394
Every register is described in detail including its name, alternate name (optional),...