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
69 }
70
73
74 // Allocate a spare memory area to store the persistent variable's
75 // contents.
76
77 const bool zero_memory = false;
79 const uint64_t malloc_size =
80 llvm::expectedToOptional(m_persistent_variable_sp->GetByteSize())
81 .value_or(0);
82 auto address_or_error = map.Malloc(
83 malloc_size, 8, lldb::ePermissionsReadable | lldb::ePermissionsWritable,
84 IRMemoryMap::eAllocationPolicyMirror, zero_memory, &used_policy);
85 if (!address_or_error) {
87 "couldn't allocate a memory area to store %s: %s",
88 m_persistent_variable_sp->GetName().GetCString(),
89 toString(address_or_error.takeError()).c_str());
90 return;
91 }
92 lldb::addr_t mem = *address_or_error;
93
95 log, "Allocated 0x%" PRIx64 "bytes for %s (0x%" PRIx64 ") successfully",
96 malloc_size, m_persistent_variable_sp->GetName().GetCString(), mem);
97
98 // Put the location of the spare memory into the live data of the
99 // ValueObject.
100
103 m_persistent_variable_sp->GetCompilerType(),
105 map.GetAddressByteSize());
106
107 if (used_policy == IRMemoryMap::eAllocationPolicyMirror) {
108 if (m_persistent_variable_sp->m_flags &
110 // Clear the flag if the variable will never be deallocated.
111 Status leak_error;
112 map.Leak(mem, leak_error);
113 m_persistent_variable_sp->m_flags &=
114 ~ExpressionVariable::EVNeedsAllocation;
115 }
116 } else {
117 // If we cannot allocate memory in the process,
118 // - clear the 'EVKeepInTarget' flag to ensure that 'm_live_sp' is reset
119 // during dematerialization,
120 m_persistent_variable_sp->m_flags &= ~ExpressionVariable::EVKeepInTarget;
121 // - set the 'EVNeedsFreezeDry' flag so that the value is copied to
122 // 'm_frozen_sp' during dematerialization.
124 }
125
126 // Write the contents of the variable to the area.
127
128 Status write_error;
129
130 map.WriteMemory(
131 mem, m_persistent_variable_sp->GetValueBytes(),
132 llvm::expectedToOptional(m_persistent_variable_sp->GetByteSize())
133 .value_or(0),
134 write_error);
135
136 if (!write_error.Success()) {
138 "couldn't write %s to the target: %s",
139 m_persistent_variable_sp->GetName().AsCString(),
140 write_error.AsCString());
141 return;
142 }
143 }
144
146 Status deallocate_error;
147
148 lldb::ValueObjectSP live_valobj_sp =
149 m_persistent_variable_sp->GetLiveObject();
150 map.Free((lldb::addr_t)live_valobj_sp->GetValue().GetScalar().ULongLong(),
151 deallocate_error);
152
153 live_valobj_sp.reset();
154
155 if (!deallocate_error.Success()) {
157 "couldn't deallocate memory for %s: %s",
158 m_persistent_variable_sp->GetName().GetCString(),
159 deallocate_error.AsCString());
160 }
161 }
162
164 lldb::addr_t process_address, Status &err) override {
166
167 const lldb::addr_t load_addr = process_address + m_offset;
168
169 if (log) {
170 LLDB_LOGF(log,
171 "EntityPersistentVariable::Materialize [address = 0x%" PRIx64
172 ", m_name = %s, m_flags = 0x%hx]",
173 (uint64_t)load_addr,
174 m_persistent_variable_sp->GetName().AsCString(),
175 m_persistent_variable_sp->m_flags);
176 }
177
178 if (m_persistent_variable_sp->m_flags &
180 MakeAllocation(map, err);
181 m_persistent_variable_sp->m_flags |=
183
184 if (!err.Success())
185 return;
186 }
187
188 lldb::ValueObjectSP live_valobj_sp =
189 m_persistent_variable_sp->GetLiveObject();
190 if ((m_persistent_variable_sp->m_flags &
192 live_valobj_sp) ||
193 m_persistent_variable_sp->m_flags &
195 Status write_error;
196
197 map.WriteScalarToMemory(load_addr, live_valobj_sp->GetValue().GetScalar(),
198 map.GetAddressByteSize(), write_error);
199
200 if (!write_error.Success()) {
202 "couldn't write the location of %s to memory: %s",
203 m_persistent_variable_sp->GetName().AsCString(),
204 write_error.AsCString());
205 }
206 } else {
208 "no materialization happened for persistent variable %s",
209 m_persistent_variable_sp->GetName().AsCString());
210 return;
211 }
212 }
213
215 lldb::addr_t process_address, lldb::addr_t frame_top,
216 lldb::addr_t frame_bottom, Status &err) override {
218
219 const lldb::addr_t load_addr = process_address + m_offset;
220
221 if (log) {
222 LLDB_LOGF(log,
223 "EntityPersistentVariable::Dematerialize [address = 0x%" PRIx64
224 ", m_name = %s, m_flags = 0x%hx]",
225 (uint64_t)process_address + m_offset,
226 m_persistent_variable_sp->GetName().AsCString(),
227 m_persistent_variable_sp->m_flags);
228 }
229
230 if (m_delegate) {
231 m_delegate->DidDematerialize(m_persistent_variable_sp);
232 }
233
234 lldb::ValueObjectSP live_valobj_sp =
235 m_persistent_variable_sp->GetLiveObject();
236 if ((m_persistent_variable_sp->m_flags &
238 (m_persistent_variable_sp->m_flags &
240 if (m_persistent_variable_sp->m_flags &
242 !live_valobj_sp) {
243 // If the reference comes from the program, then the
244 // ClangExpressionVariable's live variable data hasn't been set up yet.
245 // Do this now.
246
247 lldb::addr_t location;
248 Status read_error;
249
250 map.ReadPointerFromMemory(&location, load_addr, read_error);
251
252 if (!read_error.Success()) {
254 "couldn't read the address of program-allocated variable %s: %s",
255 m_persistent_variable_sp->GetName().GetCString(),
256 read_error.AsCString());
257 return;
258 }
259
262 m_persistent_variable_sp->GetCompilerType(),
263 m_persistent_variable_sp->GetName(), location, eAddressTypeLoad,
264 llvm::expectedToOptional(m_persistent_variable_sp->GetByteSize())
265 .value_or(0));
266
267 if (frame_top != LLDB_INVALID_ADDRESS &&
268 frame_bottom != LLDB_INVALID_ADDRESS && location >= frame_bottom &&
269 location <= frame_top) {
270 // If the variable is resident in the stack frame created by the
271 // expression, then it cannot be relied upon to stay around. We
272 // treat it as needing reallocation.
273 m_persistent_variable_sp->m_flags |=
275 m_persistent_variable_sp->m_flags |=
277 m_persistent_variable_sp->m_flags |=
279 m_persistent_variable_sp->m_flags &=
280 ~ExpressionVariable::EVIsProgramReference;
281 }
282 }
283
284 if (!live_valobj_sp) {
286 "couldn't find the memory area used to store %s",
287 m_persistent_variable_sp->GetName().GetCString());
288 return;
289 }
290
291 lldb::addr_t mem = live_valobj_sp->GetValue().GetScalar().ULongLong();
292
293 if (live_valobj_sp->GetValue().GetValueAddressType() !=
296 "the address of the memory area for %s is in an incorrect format",
297 m_persistent_variable_sp->GetName().GetCString());
298 return;
299 }
300
301 if (m_persistent_variable_sp->m_flags &
303 m_persistent_variable_sp->m_flags &
305 LLDB_LOGF(log, "Dematerializing %s from 0x%" PRIx64 " (size = %llu)",
306 m_persistent_variable_sp->GetName().GetCString(),
307 (uint64_t)mem,
308 (unsigned long long)llvm::expectedToOptional(
309 m_persistent_variable_sp->GetByteSize())
310 .value_or(0));
311
312 // Read the contents of the spare memory area
313
314 m_persistent_variable_sp->ValueUpdated();
315
316 Status read_error;
317
318 map.ReadMemory(
319 m_persistent_variable_sp->GetValueBytes(), mem,
320 llvm::expectedToOptional(m_persistent_variable_sp->GetByteSize())
321 .value_or(0),
322 read_error);
323
324 if (!read_error.Success()) {
326 "couldn't read the contents of %s from memory: %s",
327 m_persistent_variable_sp->GetName().GetCString(),
328 read_error.AsCString());
329 return;
330 }
331 m_persistent_variable_sp->m_flags &=
332 ~ExpressionVariable::EVNeedsFreezeDry;
333 }
334 } else {
336 "no dematerialization happened for persistent variable %s",
337 m_persistent_variable_sp->GetName().AsCString());
338 return;
339 }
340
341 if (m_persistent_variable_sp->m_flags &
343 !(m_persistent_variable_sp->m_flags &
345 DestroyAllocation(map, err);
346 if (!err.Success())
347 return;
348 }
349 }
350
351 void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
352 Log *log) override {
353 StreamString dump_stream;
354
355 Status err;
356
357 const lldb::addr_t load_addr = process_address + m_offset;
358
359 dump_stream.Printf("0x%" PRIx64 ": EntityPersistentVariable (%s)\n",
360 load_addr,
361 m_persistent_variable_sp->GetName().AsCString());
362
363 {
364 dump_stream.Printf("Pointer:\n");
365
366 DataBufferHeap data(m_size, 0);
367
368 map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
369
370 if (!err.Success()) {
371 dump_stream.Printf(" <could not be read>\n");
372 } else {
373 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
374 load_addr);
375
376 dump_stream.PutChar('\n');
377 }
378 }
379
380 {
381 dump_stream.Printf("Target:\n");
382
383 lldb::addr_t target_address;
384
385 map.ReadPointerFromMemory(&target_address, load_addr, err);
386
387 if (!err.Success()) {
388 dump_stream.Printf(" <could not be read>\n");
389 } else {
390 DataBufferHeap data(
391 llvm::expectedToOptional(m_persistent_variable_sp->GetByteSize())
392 .value_or(0),
393 0);
394
395 map.ReadMemory(
396 data.GetBytes(), target_address,
397 llvm::expectedToOptional(m_persistent_variable_sp->GetByteSize())
398 .value_or(0),
399 err);
400
401 if (!err.Success()) {
402 dump_stream.Printf(" <could not be read>\n");
403 } else {
404 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
405 target_address);
406
407 dump_stream.PutChar('\n');
408 }
409 }
410 }
411
412 log->PutString(dump_stream.GetString());
413 }
414
415 void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}
416
417private:
420};
421
423 lldb::ExpressionVariableSP &persistent_variable_sp,
424 PersistentVariableDelegate *delegate, Status &err) {
425 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
426 *iter = std::make_unique<EntityPersistentVariable>(persistent_variable_sp,
427 delegate);
428 uint32_t ret = AddStructMember(**iter);
429 (*iter)->SetOffset(ret);
430 return ret;
431}
432
433/// Base class for materialization of Variables and ValueObjects.
434///
435/// Subclasses specify how to obtain the Value which is to be
436/// materialized.
438public:
439 virtual ~EntityVariableBase() = default;
440
442 // Hard-coding to maximum size of a pointer since all variables are
443 // materialized by reference
446 }
447
449 lldb::addr_t process_address, Status &err) override {
451
452 const lldb::addr_t load_addr = process_address + m_offset;
453 if (log) {
454 LLDB_LOGF(log,
455 "EntityVariable::Materialize [address = 0x%" PRIx64
456 ", m_variable_sp = %s]",
457 (uint64_t)load_addr, GetName().GetCString());
458 }
459
460 ExecutionContextScope *scope = frame_sp.get();
461
462 if (!scope)
463 scope = map.GetBestExecutionContextScope();
464
465 lldb::ValueObjectSP valobj_sp = SetupValueObject(scope);
466
467 if (!valobj_sp) {
469 "couldn't get a value object for variable %s", GetName().AsCString());
470 return;
471 }
472
473 Status valobj_error = valobj_sp->GetError().Clone();
474
475 if (valobj_error.Fail()) {
477 "couldn't get the value of variable %s: %s", GetName().AsCString(),
478 valobj_error.AsCString());
479 return;
480 }
481
482 if (m_is_reference) {
483 DataExtractor valobj_extractor;
484 Status extract_error;
485 valobj_sp->GetData(valobj_extractor, extract_error);
486
487 if (!extract_error.Success()) {
489 "couldn't read contents of reference variable %s: %s",
490 GetName().AsCString(), extract_error.AsCString());
491 return;
492 }
493
494 lldb::offset_t offset = 0;
495 lldb::addr_t reference_addr = valobj_extractor.GetAddress(&offset);
496
497 Status write_error;
498 map.WritePointerToMemory(load_addr, reference_addr, write_error);
499
500 if (!write_error.Success()) {
502 "couldn't write the contents of reference "
503 "variable %s to memory: %s",
504 GetName().AsCString(), write_error.AsCString());
505 return;
506 }
507 } else {
508 lldb::addr_t addr_of_valobj =
509 valobj_sp->GetAddressOf(/*scalar_is_load_address=*/false).address;
510 if (addr_of_valobj != LLDB_INVALID_ADDRESS) {
511 Status write_error;
512 map.WritePointerToMemory(load_addr, addr_of_valobj, write_error);
513
514 if (!write_error.Success()) {
516 "couldn't write the address of variable %s to memory: %s",
517 GetName().AsCString(), write_error.AsCString());
518 return;
519 }
520 } else {
521 DataExtractor data;
522 Status extract_error;
523 valobj_sp->GetData(data, extract_error);
524 if (!extract_error.Success()) {
526 "couldn't get the value of %s: %s", GetName().AsCString(),
527 extract_error.AsCString());
528 return;
529 }
530
533 "trying to create a temporary region for %s but one exists",
534 GetName().AsCString());
535 return;
536 }
537
538 if (data.GetByteSize() <
539 llvm::expectedToOptional(GetByteSize(scope)).value_or(0)) {
540 if (data.GetByteSize() == 0 && !LocationExpressionIsValid()) {
542 "the variable '%s' has no location, "
543 "it may have been optimized out",
544 GetName().AsCString());
545 } else {
547 "size of variable %s (%" PRIu64
548 ") is larger than the ValueObject's size (%" PRIu64 ")",
549 GetName().AsCString(),
550 llvm::expectedToOptional(GetByteSize(scope)).value_or(0),
551 data.GetByteSize());
552 }
553 return;
554 }
555
556 std::optional<size_t> opt_bit_align = GetTypeBitAlign(scope);
557 if (!opt_bit_align) {
559 "can't get the type alignment for %s", GetName().AsCString());
560 return;
561 }
562
563 size_t byte_align = (*opt_bit_align + 7) / 8;
564
565 const bool zero_memory = false;
566 if (auto address_or_error = map.Malloc(
567 data.GetByteSize(), byte_align,
568 lldb::ePermissionsReadable | lldb::ePermissionsWritable,
570 m_temporary_allocation = *address_or_error;
571 } else {
573 "couldn't allocate a temporary region for %s: %s",
574 GetName().AsCString(),
575 toString(address_or_error.takeError()).c_str());
576 return;
577 }
578
580
581 m_original_data = std::make_shared<DataBufferHeap>(data.GetDataStart(),
582 data.GetByteSize());
583
584 Status write_error;
585
587 data.GetByteSize(), write_error);
588
589 if (!write_error.Success()) {
591 "couldn't write to the temporary region for %s: %s",
592 GetName().AsCString(), write_error.AsCString());
593 return;
594 }
595
596 Status pointer_write_error;
597
599 pointer_write_error);
600
601 if (!pointer_write_error.Success()) {
603 "couldn't write the address of the temporary region for %s: %s",
604 GetName().AsCString(), pointer_write_error.AsCString());
605 }
606 }
607 }
608 }
609
611 lldb::addr_t process_address, lldb::addr_t frame_top,
612 lldb::addr_t frame_bottom, Status &err) override {
614
615 const lldb::addr_t load_addr = process_address + m_offset;
616 if (log) {
617 LLDB_LOGF(log,
618 "EntityVariable::Dematerialize [address = 0x%" PRIx64
619 ", m_variable_sp = %s]",
620 (uint64_t)load_addr, GetName().AsCString());
621 }
622
624 ExecutionContextScope *scope = frame_sp.get();
625
626 if (!scope)
627 scope = map.GetBestExecutionContextScope();
628
629 lldb::ValueObjectSP valobj_sp = SetupValueObject(scope);
630
631 if (!valobj_sp) {
633 "couldn't get a value object for variable %s",
634 GetName().AsCString());
635 return;
636 }
637
639
640 Status extract_error;
641
642 map.GetMemoryData(
644 llvm::expectedToOptional(valobj_sp->GetByteSize()).value_or(0),
645 extract_error);
646
647 if (!extract_error.Success()) {
649 "couldn't get the data for variable %s", GetName().AsCString());
650 return;
651 }
652
653 bool actually_write = true;
654
655 if (m_original_data) {
656 if ((data.GetByteSize() == m_original_data->GetByteSize()) &&
657 !memcmp(m_original_data->GetBytes(), data.GetDataStart(),
658 data.GetByteSize())) {
659 actually_write = false;
660 }
661 }
662
663 Status set_error;
664
665 if (actually_write) {
666 valobj_sp->SetData(data, set_error);
667
668 if (!set_error.Success()) {
670 "couldn't write the new contents of %s back into the variable",
671 GetName().AsCString());
672 return;
673 }
674 }
675
676 Status free_error;
677
678 map.Free(m_temporary_allocation, free_error);
679
680 if (!free_error.Success()) {
682 "couldn't free the temporary region for %s: %s",
683 GetName().AsCString(), free_error.AsCString());
684 return;
685 }
686
687 m_original_data.reset();
690 }
691 }
692
693 void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
694 Log *log) override {
695 StreamString dump_stream;
696
697 const lldb::addr_t load_addr = process_address + m_offset;
698 dump_stream.Printf("0x%" PRIx64 ": EntityVariable\n", load_addr);
699
700 Status err;
701
703
704 {
705 dump_stream.Printf("Pointer:\n");
706
707 DataBufferHeap data(m_size, 0);
708
709 map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
710
711 if (!err.Success()) {
712 dump_stream.Printf(" <could not be read>\n");
713 } else {
714 DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
715 map.GetByteOrder(), map.GetAddressByteSize());
716
717 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
718 load_addr);
719
720 lldb::offset_t offset = 0;
721
722 ptr = extractor.GetAddress(&offset);
723
724 dump_stream.PutChar('\n');
725 }
726 }
727
729 dump_stream.Printf("Points to process memory:\n");
730 } else {
731 dump_stream.Printf("Temporary allocation:\n");
732 }
733
734 if (ptr == LLDB_INVALID_ADDRESS) {
735 dump_stream.Printf(" <could not be be found>\n");
736 } else {
738
741
742 if (!err.Success()) {
743 dump_stream.Printf(" <could not be read>\n");
744 } else {
745 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
746 load_addr);
747
748 dump_stream.PutChar('\n');
749 }
750 }
751
752 log->PutString(dump_stream.GetString());
753 }
754
755 void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {
757 Status free_error;
758
759 map.Free(m_temporary_allocation, free_error);
760
763 }
764 }
765
766private:
767 virtual ConstString GetName() const = 0;
768
769 /// Creates and returns ValueObject tied to this variable
770 /// and prepares Entity for materialization.
771 ///
772 /// Called each time the Materializer (de)materializes a
773 /// variable. We re-create the ValueObject based on the
774 /// current ExecutionContextScope since clients such as
775 /// conditional breakpoints may materialize the same
776 /// EntityVariable multiple times with different frames.
777 ///
778 /// Each subsequent use of the EntityVariableBase interface
779 /// will query the newly created ValueObject until this
780 /// function is called again.
781 virtual lldb::ValueObjectSP
783
784 /// Returns size in bytes of the type associated with this variable
785 ///
786 /// \returns On success, returns byte size of the type associated
787 /// with this variable. Returns std::nullopt otherwise.
788 virtual llvm::Expected<uint64_t>
790
791 /// Returns 'true' if the location expression associated with this variable
792 /// is valid.
793 virtual bool LocationExpressionIsValid() const = 0;
794
795 /// Returns alignment of the type associated with this variable in bits.
796 ///
797 /// \returns On success, returns alignment in bits for the type associated
798 /// with this variable. Returns std::nullopt otherwise.
799 virtual std::optional<size_t>
801
802protected:
803 bool m_is_reference = false;
807};
808
809/// Represents an Entity constructed from a VariableSP.
810///
811/// This class is used for materialization of variables for which
812/// the user has a VariableSP on hand. The ValueObject is then
813/// derived from the associated DWARF location expression when needed
814/// by the Materializer.
816public:
817 EntityVariable(lldb::VariableSP &variable_sp) : m_variable_sp(variable_sp) {
819 m_variable_sp->GetType()->GetForwardCompilerType().IsReferenceType();
820 }
821
822 ConstString GetName() const override { return m_variable_sp->GetName(); }
823
825 assert(m_variable_sp != nullptr);
827 }
828
829 llvm::Expected<uint64_t>
830 GetByteSize(ExecutionContextScope *scope) const override {
831 return m_variable_sp->GetType()->GetByteSize(scope);
832 }
833
834 bool LocationExpressionIsValid() const override {
835 return m_variable_sp->LocationExpressionList().IsValid();
836 }
837
838 std::optional<size_t>
839 GetTypeBitAlign(ExecutionContextScope *scope) const override {
840 return m_variable_sp->GetType()->GetLayoutCompilerType().GetTypeBitAlign(
841 scope);
842 }
843
844private:
845 lldb::VariableSP m_variable_sp; ///< Variable that this entity is based on.
846};
847
848/// Represents an Entity constructed from a VariableSP.
849///
850/// This class is used for materialization of variables for
851/// which the user does not have a VariableSP available (e.g.,
852/// when materializing ivars).
854public:
856 : m_name(name), m_valobj_provider(std::move(provider)) {
857 assert(m_valobj_provider);
858 }
859
860 ConstString GetName() const override { return m_name; }
861
865
866 if (m_valobj_sp)
867 m_is_reference = m_valobj_sp->GetCompilerType().IsReferenceType();
868
869 return m_valobj_sp;
870 }
871
872 llvm::Expected<uint64_t>
873 GetByteSize(ExecutionContextScope *scope) const override {
874 if (m_valobj_sp)
875 return m_valobj_sp->GetCompilerType().GetByteSize(scope);
876
877 return llvm::createStringError("no value object");
878 }
879
880 bool LocationExpressionIsValid() const override {
881 if (m_valobj_sp)
882 return m_valobj_sp->GetError().Success();
883
884 return false;
885 }
886
887 std::optional<size_t>
888 GetTypeBitAlign(ExecutionContextScope *scope) const override {
889 if (m_valobj_sp)
890 return m_valobj_sp->GetCompilerType().GetTypeBitAlign(scope);
891
892 return {};
893 }
894
895private:
899};
900
902 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
903 *iter = std::make_unique<EntityVariable>(variable_sp);
904 uint32_t ret = AddStructMember(**iter);
905 (*iter)->SetOffset(ret);
906 return ret;
907}
908
910 ValueObjectProviderTy valobj_provider,
911 Status &err) {
912 assert(valobj_provider);
913 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
914 *iter = std::make_unique<EntityValueObject>(name, std::move(valobj_provider));
915 uint32_t ret = AddStructMember(**iter);
916 (*iter)->SetOffset(ret);
917 return ret;
918}
919
921public:
922 EntityResultVariable(const CompilerType &type, bool is_program_reference,
923 bool keep_in_memory,
925 : Entity(), m_type(type), m_is_program_reference(is_program_reference),
926 m_keep_in_memory(keep_in_memory), m_delegate(delegate) {
927 // Hard-coding to maximum size of a pointer since all results are
928 // materialized by reference
931 }
932
934 lldb::addr_t process_address, Status &err) override {
938 "Trying to create a temporary region for the result "
939 "but one exists");
940 return;
941 }
942
943 const lldb::addr_t load_addr = process_address + m_offset;
944
945 ExecutionContextScope *exe_scope = frame_sp.get();
946 if (!exe_scope)
947 exe_scope = map.GetBestExecutionContextScope();
948
949 auto byte_size_or_err = m_type.GetByteSize(exe_scope);
950 if (!byte_size_or_err) {
951 err = Status::FromError(byte_size_or_err.takeError());
952 return;
953 }
954 auto byte_size = *byte_size_or_err;
955
956 std::optional<size_t> opt_bit_align = m_type.GetTypeBitAlign(exe_scope);
957 if (!opt_bit_align) {
959 "can't get the alignment of type \"%s\"",
960 m_type.GetTypeName().AsCString());
961 return;
962 }
963
964 size_t byte_align = (*opt_bit_align + 7) / 8;
965
966 const bool zero_memory = true;
967 if (auto address_or_error = map.Malloc(
968 byte_size, byte_align,
969 lldb::ePermissionsReadable | lldb::ePermissionsWritable,
971 m_temporary_allocation = *address_or_error;
972 } else {
974 "couldn't allocate a temporary region for the result: %s",
975 toString(address_or_error.takeError()).c_str());
976 return;
977 }
978
979 m_temporary_allocation_size = byte_size;
980
981 Status pointer_write_error;
982
984 pointer_write_error);
985
986 if (!pointer_write_error.Success()) {
988 "couldn't write the address of the "
989 "temporary region for the result: %s",
990 pointer_write_error.AsCString());
991 }
992 }
993 }
994
996 lldb::addr_t process_address, lldb::addr_t frame_top,
997 lldb::addr_t frame_bottom, Status &err) override {
998 err.Clear();
999
1000 ExecutionContextScope *exe_scope = frame_sp.get();
1001 if (!exe_scope)
1002 exe_scope = map.GetBestExecutionContextScope();
1003
1004 if (!exe_scope) {
1006 "Couldn't dematerialize a result variable: invalid "
1007 "execution context scope");
1008 return;
1009 }
1010
1011 lldb::addr_t address;
1012 Status read_error;
1013 const lldb::addr_t load_addr = process_address + m_offset;
1014
1015 map.ReadPointerFromMemory(&address, load_addr, read_error);
1016
1017 if (!read_error.Success()) {
1019 "Couldn't dematerialize a result variable: couldn't "
1020 "read its address");
1021 return;
1022 }
1023
1024 lldb::TargetSP target_sp = exe_scope->CalculateTarget();
1025
1026 if (!target_sp) {
1028 "Couldn't dematerialize a result variable: no target");
1029 return;
1030 }
1031
1032 auto type_system_or_err =
1033 target_sp->GetScratchTypeSystemForLanguage(m_type.GetMinimumLanguage());
1034
1035 if (auto error = type_system_or_err.takeError()) {
1037 "Couldn't dematerialize a result variable: "
1038 "couldn't get the corresponding type "
1039 "system: %s",
1040 llvm::toString(std::move(error)).c_str());
1041 return;
1042 }
1043 auto ts = *type_system_or_err;
1044 if (!ts) {
1046 "Couldn't dematerialize a result variable: "
1047 "couldn't corresponding type system is "
1048 "no longer live.");
1049 return;
1050 }
1051 PersistentExpressionState *persistent_state =
1052 ts->GetPersistentExpressionState();
1053
1054 if (!persistent_state) {
1056 "Couldn't dematerialize a result variable: "
1057 "corresponding type system doesn't handle persistent "
1058 "variables");
1059 return;
1060 }
1061
1062 ConstString name = m_delegate
1063 ? m_delegate->GetName()
1064 : persistent_state->GetNextPersistentVariableName();
1065
1067 exe_scope, name, m_type, map.GetByteOrder(), map.GetAddressByteSize());
1068
1069 if (!ret) {
1071 "couldn't dematerialize a result variable: "
1072 "failed to make persistent variable %s",
1073 name.AsCString());
1074 return;
1075 }
1076
1077 lldb::ProcessSP process_sp =
1079
1080 if (m_delegate) {
1081 m_delegate->DidDematerialize(ret);
1082 }
1083
1084 bool can_persist = m_is_program_reference &&
1085 !(address >= frame_bottom && address < frame_top);
1086
1087 if (can_persist && m_keep_in_memory) {
1088 ret->m_live_sp = ValueObjectConstResult::Create(exe_scope, m_type, name,
1089 address, eAddressTypeLoad,
1090 map.GetAddressByteSize());
1091 }
1092
1093 ret->ValueUpdated();
1094
1095 const size_t pvar_byte_size =
1096 llvm::expectedToOptional(ret->GetByteSize()).value_or(0);
1097 uint8_t *pvar_data = ret->GetValueBytes();
1098
1099 map.ReadMemory(pvar_data, address, pvar_byte_size, read_error);
1100
1101 if (!read_error.Success()) {
1103 "Couldn't dematerialize a result variable: couldn't read its memory");
1104 return;
1105 }
1106
1107 if (!can_persist || !m_keep_in_memory) {
1109
1111 Status free_error;
1112 map.Free(m_temporary_allocation, free_error);
1113 }
1114 } else {
1115 ret->m_flags |= m_is_program_reference
1118 }
1119
1122 }
1123
1124 void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
1125 Log *log) override {
1126 StreamString dump_stream;
1127
1128 const lldb::addr_t load_addr = process_address + m_offset;
1129
1130 dump_stream.Printf("0x%" PRIx64 ": EntityResultVariable\n", load_addr);
1131
1132 Status err;
1133
1135
1136 {
1137 dump_stream.Printf("Pointer:\n");
1138
1139 DataBufferHeap data(m_size, 0);
1140
1141 map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
1142
1143 if (!err.Success()) {
1144 dump_stream.Printf(" <could not be read>\n");
1145 } else {
1146 DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
1147 map.GetByteOrder(), map.GetAddressByteSize());
1148
1149 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
1150 load_addr);
1151
1152 lldb::offset_t offset = 0;
1153
1154 ptr = extractor.GetAddress(&offset);
1155
1156 dump_stream.PutChar('\n');
1157 }
1158 }
1159
1161 dump_stream.Printf("Points to process memory:\n");
1162 } else {
1163 dump_stream.Printf("Temporary allocation:\n");
1164 }
1165
1166 if (ptr == LLDB_INVALID_ADDRESS) {
1167 dump_stream.Printf(" <could not be be found>\n");
1168 } else {
1170
1173
1174 if (!err.Success()) {
1175 dump_stream.Printf(" <could not be read>\n");
1176 } else {
1177 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
1178 load_addr);
1179
1180 dump_stream.PutChar('\n');
1181 }
1182 }
1183
1184 log->PutString(dump_stream.GetString());
1185 }
1186
1187 void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {
1189 Status free_error;
1190
1191 map.Free(m_temporary_allocation, free_error);
1192 }
1193
1196 }
1197
1198private:
1200 /// This is used both to control whether this result entity can (and should)
1201 /// track the value in inferior memory, as well as to control whether LLDB
1202 /// needs to allocate memory for the variable during materialization.
1205
1209};
1210
1212 bool is_program_reference,
1213 bool keep_in_memory,
1215 Status &err) {
1216 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1217 *iter = std::make_unique<EntityResultVariable>(type, is_program_reference,
1218 keep_in_memory, delegate);
1219 uint32_t ret = AddStructMember(**iter);
1220 (*iter)->SetOffset(ret);
1221 return ret;
1222}
1223
1225public:
1226 EntitySymbol(const Symbol &symbol) : Entity(), m_symbol(symbol) {
1227 // Hard-coding to maximum size of a symbol
1230 }
1231
1233 lldb::addr_t process_address, Status &err) override {
1235
1236 const lldb::addr_t load_addr = process_address + m_offset;
1237
1238 if (log) {
1239 LLDB_LOGF(log,
1240 "EntitySymbol::Materialize [address = 0x%" PRIx64
1241 ", m_symbol = %s]",
1242 (uint64_t)load_addr, m_symbol.GetName().AsCString());
1243 }
1244
1245 const Address sym_address = m_symbol.GetAddress();
1246
1247 ExecutionContextScope *exe_scope = frame_sp.get();
1248 if (!exe_scope)
1249 exe_scope = map.GetBestExecutionContextScope();
1250
1251 lldb::TargetSP target_sp;
1252
1253 if (exe_scope)
1254 target_sp = map.GetBestExecutionContextScope()->CalculateTarget();
1255
1256 if (!target_sp) {
1258 "couldn't resolve symbol %s because there is no target",
1259 m_symbol.GetName().AsCString());
1260 return;
1261 }
1262
1263 lldb::addr_t resolved_address = sym_address.GetLoadAddress(target_sp.get());
1264
1265 if (resolved_address == LLDB_INVALID_ADDRESS)
1266 resolved_address = sym_address.GetFileAddress();
1267
1268 Status pointer_write_error;
1269
1270 map.WritePointerToMemory(load_addr, resolved_address, pointer_write_error);
1271
1272 if (!pointer_write_error.Success()) {
1274 "couldn't write the address of symbol %s: %s",
1275 m_symbol.GetName().AsCString(), pointer_write_error.AsCString());
1276 return;
1277 }
1278 }
1279
1281 lldb::addr_t process_address, lldb::addr_t frame_top,
1282 lldb::addr_t frame_bottom, Status &err) override {
1284
1285 const lldb::addr_t load_addr = process_address + m_offset;
1286
1287 if (log) {
1288 LLDB_LOGF(log,
1289 "EntitySymbol::Dematerialize [address = 0x%" PRIx64
1290 ", m_symbol = %s]",
1291 (uint64_t)load_addr, m_symbol.GetName().AsCString());
1292 }
1293
1294 // no work needs to be done
1295 }
1296
1297 void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
1298 Log *log) override {
1299 StreamString dump_stream;
1300
1301 Status err;
1302
1303 const lldb::addr_t load_addr = process_address + m_offset;
1304
1305 dump_stream.Printf("0x%" PRIx64 ": EntitySymbol (%s)\n", load_addr,
1306 m_symbol.GetName().AsCString());
1307
1308 {
1309 dump_stream.Printf("Pointer:\n");
1310
1311 DataBufferHeap data(m_size, 0);
1312
1313 map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
1314
1315 if (!err.Success()) {
1316 dump_stream.Printf(" <could not be read>\n");
1317 } else {
1318 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
1319 load_addr);
1320
1321 dump_stream.PutChar('\n');
1322 }
1323 }
1324
1325 log->PutString(dump_stream.GetString());
1326 }
1327
1328 void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}
1329
1330private:
1332};
1333
1334uint32_t Materializer::AddSymbol(const Symbol &symbol_sp, Status &err) {
1335 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1336 *iter = std::make_unique<EntitySymbol>(symbol_sp);
1337 uint32_t ret = AddStructMember(**iter);
1338 (*iter)->SetOffset(ret);
1339 return ret;
1340}
1341
1343public:
1344 EntityRegister(const RegisterInfo &register_info)
1345 : Entity(), m_register_info(register_info) {
1346 // Hard-coding alignment conservatively
1347 m_size = m_register_info.byte_size;
1348 m_alignment = m_register_info.byte_size;
1349 }
1350
1352 lldb::addr_t process_address, Status &err) override {
1354
1355 const lldb::addr_t load_addr = process_address + m_offset;
1356
1357 if (log) {
1358 LLDB_LOGF(log,
1359 "EntityRegister::Materialize [address = 0x%" PRIx64
1360 ", m_register_info = %s]",
1361 (uint64_t)load_addr, m_register_info.name);
1362 }
1363
1364 RegisterValue reg_value;
1365
1366 if (!frame_sp.get()) {
1368 "couldn't materialize register %s without a stack frame",
1369 m_register_info.name);
1370 return;
1371 }
1372
1373 lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
1374
1375 if (!reg_context_sp->ReadRegister(&m_register_info, reg_value)) {
1377 "couldn't read the value of register %s", m_register_info.name);
1378 return;
1379 }
1380
1381 if (reg_value.GetByteSize() != m_register_info.byte_size) {
1383 "data for register %s had size %llu but we expected %llu",
1384 m_register_info.name, (unsigned long long)reg_value.GetByteSize(),
1385 (unsigned long long)m_register_info.byte_size);
1386 return;
1387 }
1388
1389 lldb_private::DataBufferHeap buf(reg_value.GetByteSize(), 0);
1390 reg_value.GetAsMemoryData(m_register_info, buf.GetBytes(),
1391 buf.GetByteSize(), map.GetByteOrder(), err);
1392 if (!err.Success())
1393 return;
1394
1395 m_register_contents = std::make_shared<DataBufferHeap>(buf);
1396
1397 Status write_error;
1398
1399 map.WriteMemory(load_addr, buf.GetBytes(), reg_value.GetByteSize(),
1400 write_error);
1401
1402 if (!write_error.Success()) {
1404 "couldn't write the contents of register %s: %s",
1405 m_register_info.name, write_error.AsCString());
1406 return;
1407 }
1408 }
1409
1411 lldb::addr_t process_address, lldb::addr_t frame_top,
1412 lldb::addr_t frame_bottom, Status &err) override {
1414
1415 const lldb::addr_t load_addr = process_address + m_offset;
1416
1417 if (log) {
1418 LLDB_LOGF(log,
1419 "EntityRegister::Dematerialize [address = 0x%" PRIx64
1420 ", m_register_info = %s]",
1421 (uint64_t)load_addr, m_register_info.name);
1422 }
1423
1424 Status extract_error;
1425
1426 DataExtractor register_data;
1427
1428 if (!frame_sp.get()) {
1430 "couldn't dematerialize register %s without a stack frame",
1431 m_register_info.name);
1432 return;
1433 }
1434
1435 lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
1436
1437 map.GetMemoryData(register_data, load_addr, m_register_info.byte_size,
1438 extract_error);
1439
1440 if (!extract_error.Success()) {
1442 "couldn't get the data for register %s: %s", m_register_info.name,
1443 extract_error.AsCString());
1444 return;
1445 }
1446
1447 if (!memcmp(register_data.GetDataStart(), m_register_contents->GetBytes(),
1448 register_data.GetByteSize())) {
1449 // No write required, and in particular we avoid errors if the register
1450 // wasn't writable
1451
1452 m_register_contents.reset();
1453 return;
1454 }
1455
1456 m_register_contents.reset();
1457
1458 RegisterValue register_value(register_data.GetData(),
1459 register_data.GetByteOrder());
1460
1461 if (!reg_context_sp->WriteRegister(&m_register_info, register_value)) {
1463 "couldn't write the value of register %s", m_register_info.name);
1464 return;
1465 }
1466 }
1467
1468 void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
1469 Log *log) override {
1470 StreamString dump_stream;
1471
1472 Status err;
1473
1474 const lldb::addr_t load_addr = process_address + m_offset;
1475
1476 dump_stream.Printf("0x%" PRIx64 ": EntityRegister (%s)\n", load_addr,
1477 m_register_info.name);
1478
1479 {
1480 dump_stream.Printf("Value:\n");
1481
1482 DataBufferHeap data(m_size, 0);
1483
1484 map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
1485
1486 if (!err.Success()) {
1487 dump_stream.Printf(" <could not be read>\n");
1488 } else {
1489 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
1490 load_addr);
1491
1492 dump_stream.PutChar('\n');
1493 }
1494 }
1495
1496 log->PutString(dump_stream.GetString());
1497 }
1498
1499 void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}
1500
1501private:
1504};
1505
1506uint32_t Materializer::AddRegister(const RegisterInfo &register_info,
1507 Status &err) {
1508 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1509 *iter = std::make_unique<EntityRegister>(register_info);
1510 uint32_t ret = AddStructMember(**iter);
1511 (*iter)->SetOffset(ret);
1512 return ret;
1513}
1514
1516 DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
1517
1518 if (dematerializer_sp)
1519 dematerializer_sp->Wipe();
1520}
1521
1524 lldb::addr_t process_address, Status &error) {
1525 ExecutionContextScope *exe_scope = frame_sp.get();
1526 if (!exe_scope)
1527 exe_scope = map.GetBestExecutionContextScope();
1528
1529 DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
1530
1531 if (dematerializer_sp) {
1532 error =
1533 Status::FromErrorString("Couldn't materialize: already materialized");
1534 }
1535
1536 DematerializerSP ret(
1537 new Dematerializer(*this, frame_sp, map, process_address));
1538
1539 if (!exe_scope) {
1540 error =
1541 Status::FromErrorString("Couldn't materialize: target doesn't exist");
1542 }
1543
1544 for (EntityUP &entity_up : m_entities) {
1545 entity_up->Materialize(frame_sp, map, process_address, error);
1546
1547 if (!error.Success())
1548 return DematerializerSP();
1549 }
1550
1551 if (Log *log = GetLog(LLDBLog::Expressions)) {
1552 LLDB_LOGF(
1553 log,
1554 "Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64
1555 ") materialized:",
1556 static_cast<void *>(frame_sp.get()), process_address);
1557 for (EntityUP &entity_up : m_entities)
1558 entity_up->DumpToLog(map, process_address, log);
1559 }
1560
1561 m_dematerializer_wp = ret;
1562
1563 return ret;
1564}
1565
1567 lldb::addr_t frame_bottom,
1568 lldb::addr_t frame_top) {
1569 lldb::StackFrameSP frame_sp;
1570
1571 lldb::ThreadSP thread_sp = m_thread_wp.lock();
1572 if (thread_sp)
1573 frame_sp = thread_sp->GetFrameWithStackID(m_stack_id);
1574
1575 ExecutionContextScope *exe_scope = frame_sp.get();
1576 if (!exe_scope)
1577 exe_scope = m_map->GetBestExecutionContextScope();
1578
1579 if (!IsValid()) {
1581 "Couldn't dematerialize: invalid dematerializer");
1582 }
1583
1584 if (!exe_scope) {
1585 error = Status::FromErrorString("Couldn't dematerialize: target is gone");
1586 } else {
1587 if (Log *log = GetLog(LLDBLog::Expressions)) {
1588 LLDB_LOGF(log,
1589 "Materializer::Dematerialize (frame_sp = %p, process_address "
1590 "= 0x%" PRIx64 ") about to dematerialize:",
1591 static_cast<void *>(frame_sp.get()), m_process_address);
1592 for (EntityUP &entity_up : m_materializer->m_entities)
1593 entity_up->DumpToLog(*m_map, m_process_address, log);
1594 }
1595
1596 for (EntityUP &entity_up : m_materializer->m_entities) {
1597 entity_up->Dematerialize(frame_sp, *m_map, m_process_address, frame_top,
1598 frame_bottom, error);
1599
1600 if (!error.Success())
1601 break;
1602 }
1603 }
1604
1605 Wipe();
1606}
1607
1609 if (!IsValid())
1610 return;
1611
1612 for (EntityUP &entity_up : m_materializer->m_entities) {
1613 entity_up->Wipe(*m_map, m_process_address);
1614 }
1615
1616 m_materializer = nullptr;
1617 m_map = nullptr;
1619}
1620
1622 default;
1624 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
bool m_is_program_reference
This is used both to control whether this result entity can (and should) track the value in inferior ...
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
lldb::addr_t m_temporary_allocation
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
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.
llvm::Expected< uint64_t > GetByteSize(ExecutionContextScope *scope) const override
Returns size in bytes of the type associated with this variable.
lldb::ValueObjectSP SetupValueObject(ExecutionContextScope *scope) override
Creates and returns ValueObject tied to this variable and prepares Entity for materialization.
EntityValueObject(ConstString name, ValueObjectProviderTy provider)
lldb::DataBufferSP m_original_data
size_t m_temporary_allocation_size
lldb::addr_t m_temporary_allocation
void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Status &err) override
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.
virtual llvm::Expected< uint64_t > GetByteSize(ExecutionContextScope *scope) const =0
Returns size in bytes of the type associated with this variable.
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
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.
llvm::Expected< 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:301
lldb::addr_t GetFileAddress() const
Get the file address.
Definition Address.cpp:281
Generic representation of a type in a programming language.
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.
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.
virtual 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:35
void Free(lldb::addr_t process_address, Status &error)
lldb::ByteOrder GetByteOrder()
llvm::Expected< lldb::addr_t > Malloc(size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, bool zero_memory, AllocationPolicy *used_policy=nullptr)
void ReadPointerFromMemory(lldb::addr_t *address, lldb::addr_t process_address, Status &error)
ExecutionContextScope * GetBestExecutionContextScope() const
void GetMemoryData(DataExtractor &extractor, lldb::addr_t process_address, size_t size, Status &error)
void WritePointerToMemory(lldb::addr_t process_address, lldb::addr_t pointer, 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:47
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
std::shared_ptr< Dematerializer > DematerializerSP
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
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.
uint32_t GetAsMemoryData(const RegisterInfo &reg_info, void *dst, uint32_t dst_len, lldb::ByteOrder dst_byte_order, Status &error) const
An error handling class.
Definition Status.h:118
void Clear()
Clear the object state.
Definition Status.cpp:215
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
static Status FromError(llvm::Error error)
Avoid using this in new code. Migrate APIs to llvm::Expected instead.
Definition Status.cpp:137
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
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
std::function< lldb::ValueObjectSP(ConstString, StackFrame *)> ValueObjectProviderTy
Functor that returns a ValueObjectSP for a variable given its name and the StackFrame of interest.
void DumpHexBytes(Stream *s, const void *src, size_t src_len, uint32_t bytes_per_line, lldb::addr_t base_addr)
@ eAddressTypeLoad
Address is an address as in the current target inferior process.
const char * toString(AppleArm64ExceptionClass EC)
std::shared_ptr< lldb_private::StackFrame > StackFrameSP
std::shared_ptr< lldb_private::Thread > ThreadSP
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
std::shared_ptr< lldb_private::ExpressionVariable > ExpressionVariableSP
uint64_t offset_t
Definition lldb-types.h:85
std::shared_ptr< lldb_private::Process > ProcessSP
std::shared_ptr< lldb_private::Variable > VariableSP
std::shared_ptr< lldb_private::DataBuffer > DataBufferSP
uint64_t addr_t
Definition lldb-types.h:80
std::shared_ptr< lldb_private::Target > TargetSP
std::shared_ptr< lldb_private::RegisterContext > RegisterContextSP
Every register is described in detail including its name, alternate name (optional),...