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