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 {0} to the target: {1}",
139 m_persistent_variable_sp->GetName(), write_error.AsCString());
140 return;
141 }
142 }
143
145 Status deallocate_error;
146
147 lldb::ValueObjectSP live_valobj_sp =
148 m_persistent_variable_sp->GetLiveObject();
149 map.Free((lldb::addr_t)live_valobj_sp->GetValue().GetScalar().ULongLong(),
150 deallocate_error);
151
152 live_valobj_sp.reset();
153
154 if (!deallocate_error.Success()) {
156 "couldn't deallocate memory for %s: %s",
157 m_persistent_variable_sp->GetName().GetCString(),
158 deallocate_error.AsCString());
159 }
160 }
161
163 lldb::addr_t process_address, Status &err) override {
165
166 const lldb::addr_t load_addr = process_address + m_offset;
167
168 LLDB_LOG(log,
169 "EntityPersistentVariable::Materialize [address = {0:x}, m_name = "
170 "{1}, m_flags = {2:x}]",
171 (uint64_t)load_addr, m_persistent_variable_sp->GetName(),
172 m_persistent_variable_sp->m_flags);
173
174 if (m_persistent_variable_sp->m_flags &
176 MakeAllocation(map, err);
177 m_persistent_variable_sp->m_flags |=
179
180 if (!err.Success())
181 return;
182 }
183
184 lldb::ValueObjectSP live_valobj_sp =
185 m_persistent_variable_sp->GetLiveObject();
186 if ((m_persistent_variable_sp->m_flags &
188 live_valobj_sp) ||
189 m_persistent_variable_sp->m_flags &
191 Status write_error;
192
193 map.WriteScalarToMemory(load_addr, live_valobj_sp->GetValue().GetScalar(),
194 map.GetAddressByteSize(), write_error);
195
196 if (!write_error.Success()) {
198 "couldn't write the location of {0} to memory: {1}",
199 m_persistent_variable_sp->GetName(), write_error.AsCString());
200 }
201 } else {
203 "no materialization happened for persistent variable {0}",
204 m_persistent_variable_sp->GetName());
205 return;
206 }
207 }
208
210 lldb::addr_t process_address, lldb::addr_t frame_top,
211 lldb::addr_t frame_bottom, Status &err) override {
213
214 const lldb::addr_t load_addr = process_address + m_offset;
215
216 LLDB_LOG(log,
217 "EntityPersistentVariable::Dematerialize [address = {0:x}, m_name "
218 "= {1}, m_flags = {2}]",
219 (uint64_t)process_address + m_offset,
220 m_persistent_variable_sp->GetName(),
221 m_persistent_variable_sp->m_flags);
222
223 if (m_delegate) {
224 m_delegate->DidDematerialize(m_persistent_variable_sp);
225 }
226
227 lldb::ValueObjectSP live_valobj_sp =
228 m_persistent_variable_sp->GetLiveObject();
229 if ((m_persistent_variable_sp->m_flags &
231 (m_persistent_variable_sp->m_flags &
233 if (m_persistent_variable_sp->m_flags &
235 !live_valobj_sp) {
236 // If the reference comes from the program, then the
237 // ClangExpressionVariable's live variable data hasn't been set up yet.
238 // Do this now.
239
240 lldb::addr_t location;
241 Status read_error;
242
243 map.ReadPointerFromMemory(&location, load_addr, read_error);
244
245 if (!read_error.Success()) {
247 "couldn't read the address of program-allocated variable %s: %s",
248 m_persistent_variable_sp->GetName().GetCString(),
249 read_error.AsCString());
250 return;
251 }
252
255 m_persistent_variable_sp->GetCompilerType(),
256 m_persistent_variable_sp->GetName(), location, eAddressTypeLoad,
257 llvm::expectedToOptional(m_persistent_variable_sp->GetByteSize())
258 .value_or(0));
259
260 if (frame_top != LLDB_INVALID_ADDRESS &&
261 frame_bottom != LLDB_INVALID_ADDRESS && location >= frame_bottom &&
262 location <= frame_top) {
263 // If the variable is resident in the stack frame created by the
264 // expression, then it cannot be relied upon to stay around. We
265 // treat it as needing reallocation.
266 m_persistent_variable_sp->m_flags |=
268 m_persistent_variable_sp->m_flags |=
270 m_persistent_variable_sp->m_flags |=
272 m_persistent_variable_sp->m_flags &=
273 ~ExpressionVariable::EVIsProgramReference;
274 }
275 }
276
277 if (!live_valobj_sp) {
279 "couldn't find the memory area used to store %s",
280 m_persistent_variable_sp->GetName().GetCString());
281 return;
282 }
283
284 lldb::addr_t mem = live_valobj_sp->GetValue().GetScalar().ULongLong();
285
286 if (live_valobj_sp->GetValue().GetValueAddressType() !=
289 "the address of the memory area for %s is in an incorrect format",
290 m_persistent_variable_sp->GetName().GetCString());
291 return;
292 }
293
294 if (m_persistent_variable_sp->m_flags &
296 m_persistent_variable_sp->m_flags &
298 LLDB_LOGF(log, "Dematerializing %s from 0x%" PRIx64 " (size = %llu)",
299 m_persistent_variable_sp->GetName().GetCString(),
300 (uint64_t)mem,
301 (unsigned long long)llvm::expectedToOptional(
302 m_persistent_variable_sp->GetByteSize())
303 .value_or(0));
304
305 // Read the contents of the spare memory area
306
307 m_persistent_variable_sp->ValueUpdated();
308
309 Status read_error;
310
311 map.ReadMemory(
312 m_persistent_variable_sp->GetValueBytes(), mem,
313 llvm::expectedToOptional(m_persistent_variable_sp->GetByteSize())
314 .value_or(0),
315 read_error);
316
317 if (!read_error.Success()) {
319 "couldn't read the contents of %s from memory: %s",
320 m_persistent_variable_sp->GetName().GetCString(),
321 read_error.AsCString());
322 return;
323 }
324 m_persistent_variable_sp->m_flags &=
325 ~ExpressionVariable::EVNeedsFreezeDry;
326 }
327 } else {
329 "no dematerialization happened for persistent variable {0}",
330 m_persistent_variable_sp->GetName());
331 return;
332 }
333
334 if (m_persistent_variable_sp->m_flags &
336 !(m_persistent_variable_sp->m_flags &
338 DestroyAllocation(map, err);
339 if (!err.Success())
340 return;
341 }
342 }
343
344 void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
345 Log *log) override {
346 StreamString dump_stream;
347
348 Status err;
349
350 const lldb::addr_t load_addr = process_address + m_offset;
351
352 dump_stream.Format("{0:x}: EntityPersistentVariable ({1})\n", load_addr,
353 m_persistent_variable_sp->GetName());
354
355 {
356 dump_stream.PutCString("Pointer:\n");
357
358 DataBufferHeap data(m_size, 0);
359
360 map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
361
362 if (!err.Success()) {
363 dump_stream.PutCString(" <could not be read>\n");
364 } else {
365 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
366 load_addr);
367
368 dump_stream.PutChar('\n');
369 }
370 }
371
372 {
373 dump_stream.PutCString("Target:\n");
374
375 lldb::addr_t target_address;
376
377 map.ReadPointerFromMemory(&target_address, load_addr, err);
378
379 if (!err.Success()) {
380 dump_stream.PutCString(" <could not be read>\n");
381 } else {
382 DataBufferHeap data(
383 llvm::expectedToOptional(m_persistent_variable_sp->GetByteSize())
384 .value_or(0),
385 0);
386
387 map.ReadMemory(
388 data.GetBytes(), target_address,
389 llvm::expectedToOptional(m_persistent_variable_sp->GetByteSize())
390 .value_or(0),
391 err);
392
393 if (!err.Success()) {
394 dump_stream.PutCString(" <could not be read>\n");
395 } else {
396 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
397 target_address);
398
399 dump_stream.PutChar('\n');
400 }
401 }
402 }
403
404 log->PutString(dump_stream.GetString());
405 }
406
407 void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}
408
409private:
412};
413
415 lldb::ExpressionVariableSP &persistent_variable_sp,
416 PersistentVariableDelegate *delegate, Status &err) {
417 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
418 *iter = std::make_unique<EntityPersistentVariable>(persistent_variable_sp,
419 delegate);
420 uint32_t ret = AddStructMember(**iter);
421 (*iter)->SetOffset(ret);
422 return ret;
423}
424
425/// Base class for materialization of Variables and ValueObjects.
426///
427/// Subclasses specify how to obtain the Value which is to be
428/// materialized.
430public:
431 virtual ~EntityVariableBase() = default;
432
434 // Hard-coding to maximum size of a pointer since all variables are
435 // materialized by reference
438 }
439
441 lldb::addr_t process_address, Status &err) override {
443
444 const lldb::addr_t load_addr = process_address + m_offset;
445 LLDB_LOGF(log,
446 "EntityVariable::Materialize [address = 0x%" PRIx64
447 ", m_variable_sp = %s]",
448 (uint64_t)load_addr, GetName().GetCString());
449
450 ExecutionContextScope *scope = frame_sp.get();
451
452 if (!scope)
453 scope = map.GetBestExecutionContextScope();
454
455 lldb::ValueObjectSP valobj_sp = SetupValueObject(scope);
456
457 if (!valobj_sp) {
459 "couldn't get a value object for variable {0}", GetName());
460 return;
461 }
462
463 Status valobj_error = valobj_sp->GetError().Clone();
464
465 if (valobj_error.Fail()) {
467 "couldn't get the value of variable {0}: {1}", GetName(),
468 valobj_error.AsCString());
469 return;
470 }
471
472 if (m_is_reference) {
473 DataExtractor valobj_extractor;
474 Status extract_error;
475 valobj_sp->GetData(valobj_extractor, extract_error);
476
477 if (!extract_error.Success()) {
479 "couldn't read contents of reference variable {0}: {1}", GetName(),
480 extract_error.AsCString());
481 return;
482 }
483
484 lldb::offset_t offset = 0;
485 lldb::addr_t reference_addr = valobj_extractor.GetAddress(&offset);
486
487 Status write_error;
488 map.WritePointerToMemory(load_addr, reference_addr, write_error);
489
490 if (!write_error.Success()) {
492 "couldn't write the contents of reference variable {} to memory: "
493 "{}",
494 GetName(), write_error.AsCString());
495 return;
496 }
497 } else {
498 lldb::addr_t addr_of_valobj =
499 valobj_sp->GetAddressOf(/*scalar_is_load_address=*/false).address;
500 if (addr_of_valobj != LLDB_INVALID_ADDRESS) {
501 Status write_error;
502 map.WritePointerToMemory(load_addr, addr_of_valobj, write_error);
503
504 if (!write_error.Success()) {
506 "couldn't write the address of variable {0} to memory: {1}",
507 GetName(), write_error.AsCString());
508 return;
509 }
510 } else {
511 DataExtractor data;
512 Status extract_error;
513 valobj_sp->GetData(data, extract_error);
514 if (!extract_error.Success()) {
516 "couldn't get the value of {0}: {1}", GetName(),
517 extract_error.AsCString());
518 return;
519 }
520
523 "trying to create a temporary region for {0} but one exists",
524 GetName());
525 return;
526 }
527
528 if (data.GetByteSize() <
529 llvm::expectedToOptional(GetByteSize(scope)).value_or(0)) {
530 if (data.GetByteSize() == 0 && !LocationExpressionIsValid()) {
532 "the variable '{0}' has no location, "
533 "it may have been optimized out",
534 GetName());
535 } else {
537 "size of variable {0} ({1}) is larger than the ValueObject's "
538 "size ({2})",
539 GetName(),
540 llvm::expectedToOptional(GetByteSize(scope)).value_or(0),
541 data.GetByteSize());
542 }
543 return;
544 }
545
546 std::optional<size_t> opt_bit_align = GetTypeBitAlign(scope);
547 if (!opt_bit_align) {
549 "can't get the type alignment for {0}", GetName());
550 return;
551 }
552
553 size_t byte_align = (*opt_bit_align + 7) / 8;
554
555 const bool zero_memory = false;
556 if (auto address_or_error = map.Malloc(
557 data.GetByteSize(), byte_align,
558 lldb::ePermissionsReadable | lldb::ePermissionsWritable,
560 m_temporary_allocation = *address_or_error;
561 } else {
563 "couldn't allocate a temporary region for {0}: {1}", GetName(),
564 toString(address_or_error.takeError()));
565 return;
566 }
567
569
570 m_original_data = std::make_shared<DataBufferHeap>(data.GetDataStart(),
571 data.GetByteSize());
572
573 Status write_error;
574
576 data.GetByteSize(), write_error);
577
578 if (!write_error.Success()) {
580 "couldn't write to the temporary region for {0}: {1}", GetName(),
581 write_error.AsCString());
582 return;
583 }
584
585 Status pointer_write_error;
586
588 pointer_write_error);
589
590 if (!pointer_write_error.Success()) {
592 "couldn't write the address of the temporary region for {0}: {1}",
593 GetName(), pointer_write_error.AsCString());
594 }
595 }
596 }
597 }
598
600 lldb::addr_t process_address, lldb::addr_t frame_top,
601 lldb::addr_t frame_bottom, Status &err) override {
603
604 const lldb::addr_t load_addr = process_address + m_offset;
605 LLDB_LOG(
606 log,
607 "EntityVariable::Dematerialize [address = {0:x}, m_variable_sp = {1}]",
608 (uint64_t)load_addr, GetName());
609
611 ExecutionContextScope *scope = frame_sp.get();
612
613 if (!scope)
614 scope = map.GetBestExecutionContextScope();
615
616 lldb::ValueObjectSP valobj_sp = SetupValueObject(scope);
617
618 if (!valobj_sp) {
620 "couldn't get a value object for variable {0}", GetName());
621 return;
622 }
623
625
626 Status extract_error;
627
628 map.GetMemoryData(
630 llvm::expectedToOptional(valobj_sp->GetByteSize()).value_or(0),
631 extract_error);
632
633 if (!extract_error.Success()) {
635 "couldn't get the data for variable {0}", GetName());
636 return;
637 }
638
639 bool actually_write = true;
640
641 if (m_original_data) {
642 if ((data.GetByteSize() == m_original_data->GetByteSize()) &&
643 !memcmp(m_original_data->GetBytes(), data.GetDataStart(),
644 data.GetByteSize())) {
645 actually_write = false;
646 }
647 }
648
649 Status set_error;
650
651 if (actually_write) {
652 valobj_sp->SetData(data, set_error);
653
654 if (!set_error.Success()) {
656 "couldn't write the new contents of {0} back into the variable",
657 GetName());
658 return;
659 }
660 }
661
662 Status free_error;
663
664 map.Free(m_temporary_allocation, free_error);
665
666 if (!free_error.Success()) {
668 "couldn't free the temporary region for {0}: {1}", GetName(),
669 free_error.AsCString());
670 return;
671 }
672
673 m_original_data.reset();
676 }
677 }
678
679 void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
680 Log *log) override {
681 StreamString dump_stream;
682
683 const lldb::addr_t load_addr = process_address + m_offset;
684 dump_stream.Printf("0x%" PRIx64 ": EntityVariable\n", load_addr);
685
686 Status err;
687
689
690 {
691 dump_stream.PutCString("Pointer:\n");
692
693 DataBufferHeap data(m_size, 0);
694
695 map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
696
697 if (!err.Success()) {
698 dump_stream.PutCString(" <could not be read>\n");
699 } else {
700 DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
701 map.GetByteOrder(), map.GetAddressByteSize());
702
703 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
704 load_addr);
705
706 lldb::offset_t offset = 0;
707
708 ptr = extractor.GetAddress(&offset);
709
710 dump_stream.PutChar('\n');
711 }
712 }
713
715 dump_stream.PutCString("Points to process memory:\n");
716 } else {
717 dump_stream.PutCString("Temporary allocation:\n");
718 }
719
720 if (ptr == LLDB_INVALID_ADDRESS) {
721 dump_stream.PutCString(" <could not be be found>\n");
722 } else {
724
727
728 if (!err.Success()) {
729 dump_stream.PutCString(" <could not be read>\n");
730 } else {
731 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
732 load_addr);
733
734 dump_stream.PutChar('\n');
735 }
736 }
737
738 log->PutString(dump_stream.GetString());
739 }
740
741 void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {
743 Status free_error;
744
745 map.Free(m_temporary_allocation, free_error);
746
749 }
750 }
751
752private:
753 virtual ConstString GetName() const = 0;
754
755 /// Creates and returns ValueObject tied to this variable
756 /// and prepares Entity for materialization.
757 ///
758 /// Called each time the Materializer (de)materializes a
759 /// variable. We re-create the ValueObject based on the
760 /// current ExecutionContextScope since clients such as
761 /// conditional breakpoints may materialize the same
762 /// EntityVariable multiple times with different frames.
763 ///
764 /// Each subsequent use of the EntityVariableBase interface
765 /// will query the newly created ValueObject until this
766 /// function is called again.
767 virtual lldb::ValueObjectSP
769
770 /// Returns size in bytes of the type associated with this variable
771 ///
772 /// \returns On success, returns byte size of the type associated
773 /// with this variable. Returns std::nullopt otherwise.
774 virtual llvm::Expected<uint64_t>
776
777 /// Returns 'true' if the location expression associated with this variable
778 /// is valid.
779 virtual bool LocationExpressionIsValid() const = 0;
780
781 /// Returns alignment of the type associated with this variable in bits.
782 ///
783 /// \returns On success, returns alignment in bits for the type associated
784 /// with this variable. Returns std::nullopt otherwise.
785 virtual std::optional<size_t>
787
788protected:
789 bool m_is_reference = false;
793};
794
795/// Represents an Entity constructed from a VariableSP.
796///
797/// This class is used for materialization of variables for which
798/// the user has a VariableSP on hand. The ValueObject is then
799/// derived from the associated DWARF location expression when needed
800/// by the Materializer.
802public:
803 EntityVariable(lldb::VariableSP &variable_sp) : m_variable_sp(variable_sp) {
805 m_variable_sp->GetType()->GetForwardCompilerType().IsReferenceType();
806 }
807
808 ConstString GetName() const override { return m_variable_sp->GetName(); }
809
811 assert(m_variable_sp != nullptr);
813 }
814
815 llvm::Expected<uint64_t>
816 GetByteSize(ExecutionContextScope *scope) const override {
817 return m_variable_sp->GetType()->GetByteSize(scope);
818 }
819
820 bool LocationExpressionIsValid() const override {
821 return m_variable_sp->LocationExpressionList().IsValid();
822 }
823
824 std::optional<size_t>
825 GetTypeBitAlign(ExecutionContextScope *scope) const override {
826 return m_variable_sp->GetType()->GetLayoutCompilerType().GetTypeBitAlign(
827 scope);
828 }
829
830private:
831 lldb::VariableSP m_variable_sp; ///< Variable that this entity is based on.
832};
833
834/// Represents an Entity constructed from a VariableSP.
835///
836/// This class is used for materialization of variables for
837/// which the user does not have a VariableSP available (e.g.,
838/// when materializing ivars).
840public:
842 : m_name(name), m_valobj_provider(std::move(provider)) {
843 assert(m_valobj_provider);
844 }
845
846 ConstString GetName() const override { return m_name; }
847
851
852 if (m_valobj_sp)
853 m_is_reference = m_valobj_sp->GetCompilerType().IsReferenceType();
854
855 return m_valobj_sp;
856 }
857
858 llvm::Expected<uint64_t>
859 GetByteSize(ExecutionContextScope *scope) const override {
860 if (m_valobj_sp)
861 return m_valobj_sp->GetCompilerType().GetByteSize(scope);
862
863 return llvm::createStringError("no value object");
864 }
865
866 bool LocationExpressionIsValid() const override {
867 if (m_valobj_sp)
868 return m_valobj_sp->GetError().Success();
869
870 return false;
871 }
872
873 std::optional<size_t>
874 GetTypeBitAlign(ExecutionContextScope *scope) const override {
875 if (m_valobj_sp)
876 return m_valobj_sp->GetCompilerType().GetTypeBitAlign(scope);
877
878 return {};
879 }
880
881private:
885};
886
888 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
889 *iter = std::make_unique<EntityVariable>(variable_sp);
890 uint32_t ret = AddStructMember(**iter);
891 (*iter)->SetOffset(ret);
892 return ret;
893}
894
896 ValueObjectProviderTy valobj_provider,
897 Status &err) {
898 assert(valobj_provider);
899 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
900 *iter = std::make_unique<EntityValueObject>(name, std::move(valobj_provider));
901 uint32_t ret = AddStructMember(**iter);
902 (*iter)->SetOffset(ret);
903 return ret;
904}
905
907public:
908 EntityResultVariable(const CompilerType &type, bool is_program_reference,
909 bool keep_in_memory,
911 : Entity(), m_type(type), m_is_program_reference(is_program_reference),
912 m_keep_in_memory(keep_in_memory), m_delegate(delegate) {
913 // Hard-coding to maximum size of a pointer since all results are
914 // materialized by reference
917 }
918
920 lldb::addr_t process_address, Status &err) override {
924 "Trying to create a temporary region for the result "
925 "but one exists");
926 return;
927 }
928
929 const lldb::addr_t load_addr = process_address + m_offset;
930
931 ExecutionContextScope *exe_scope = frame_sp.get();
932 if (!exe_scope)
933 exe_scope = map.GetBestExecutionContextScope();
934
935 auto byte_size_or_err = m_type.GetByteSize(exe_scope);
936 if (!byte_size_or_err) {
937 err = Status::FromError(byte_size_or_err.takeError());
938 return;
939 }
940 auto byte_size = *byte_size_or_err;
941
942 std::optional<size_t> opt_bit_align = m_type.GetTypeBitAlign(exe_scope);
943 if (!opt_bit_align) {
945 "can't get the alignment of type \"{0}\"", m_type.GetTypeName());
946 return;
947 }
948
949 size_t byte_align = (*opt_bit_align + 7) / 8;
950
951 const bool zero_memory = true;
952 if (auto address_or_error = map.Malloc(
953 byte_size, byte_align,
954 lldb::ePermissionsReadable | lldb::ePermissionsWritable,
956 m_temporary_allocation = *address_or_error;
957 } else {
959 "couldn't allocate a temporary region for the result: %s",
960 toString(address_or_error.takeError()).c_str());
961 return;
962 }
963
964 m_temporary_allocation_size = byte_size;
965
966 Status pointer_write_error;
967
969 pointer_write_error);
970
971 if (!pointer_write_error.Success()) {
973 "couldn't write the address of the "
974 "temporary region for the result: %s",
975 pointer_write_error.AsCString());
976 }
977 }
978 }
979
981 lldb::addr_t process_address, lldb::addr_t frame_top,
982 lldb::addr_t frame_bottom, Status &err) override {
983 err.Clear();
984
985 ExecutionContextScope *exe_scope = frame_sp.get();
986 if (!exe_scope)
987 exe_scope = map.GetBestExecutionContextScope();
988
989 if (!exe_scope) {
991 "Couldn't dematerialize a result variable: invalid "
992 "execution context scope");
993 return;
994 }
995
996 lldb::addr_t address;
997 Status read_error;
998 const lldb::addr_t load_addr = process_address + m_offset;
999
1000 map.ReadPointerFromMemory(&address, load_addr, read_error);
1001
1002 if (!read_error.Success()) {
1004 "Couldn't dematerialize a result variable: couldn't "
1005 "read its address");
1006 return;
1007 }
1008
1009 lldb::TargetSP target_sp = exe_scope->CalculateTarget();
1010
1011 if (!target_sp) {
1013 "Couldn't dematerialize a result variable: no target");
1014 return;
1015 }
1016
1017 auto type_system_or_err =
1018 target_sp->GetScratchTypeSystemForLanguage(m_type.GetMinimumLanguage());
1019
1020 if (auto error = type_system_or_err.takeError()) {
1022 "Couldn't dematerialize a result variable: "
1023 "couldn't get the corresponding type "
1024 "system: %s",
1025 llvm::toString(std::move(error)).c_str());
1026 return;
1027 }
1028 auto ts = *type_system_or_err;
1029 if (!ts) {
1031 "Couldn't dematerialize a result variable: "
1032 "couldn't corresponding type system is "
1033 "no longer live.");
1034 return;
1035 }
1036 PersistentExpressionState *persistent_state =
1037 ts->GetPersistentExpressionState();
1038
1039 if (!persistent_state) {
1041 "Couldn't dematerialize a result variable: "
1042 "corresponding type system doesn't handle persistent "
1043 "variables");
1044 return;
1045 }
1046
1047 ConstString name = m_delegate
1048 ? m_delegate->GetName()
1049 : persistent_state->GetNextPersistentVariableName();
1050
1052 exe_scope, name, m_type, map.GetByteOrder(), map.GetAddressByteSize());
1053
1054 if (!ret) {
1056 "couldn't dematerialize a result variable: failed to make persistent "
1057 "variable {0}",
1058 name);
1059 return;
1060 }
1061
1062 lldb::ProcessSP process_sp =
1064
1065 if (m_delegate) {
1066 m_delegate->DidDematerialize(ret);
1067 }
1068
1069 bool can_persist = m_is_program_reference &&
1070 !(address >= frame_bottom && address < frame_top);
1071
1072 if (can_persist && m_keep_in_memory) {
1073 ret->m_live_sp = ValueObjectConstResult::Create(exe_scope, m_type, name,
1074 address, eAddressTypeLoad,
1075 map.GetAddressByteSize());
1076 }
1077
1078 ret->ValueUpdated();
1079
1080 const size_t pvar_byte_size =
1081 llvm::expectedToOptional(ret->GetByteSize()).value_or(0);
1082 uint8_t *pvar_data = ret->GetValueBytes();
1083
1084 map.ReadMemory(pvar_data, address, pvar_byte_size, read_error);
1085
1086 if (!read_error.Success()) {
1088 "Couldn't dematerialize a result variable: couldn't read its memory");
1089 return;
1090 }
1091
1092 if (!can_persist || !m_keep_in_memory) {
1094
1096 Status free_error;
1097 map.Free(m_temporary_allocation, free_error);
1098 }
1099 } else {
1100 ret->m_flags |= m_is_program_reference
1103 }
1104
1107 }
1108
1109 void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
1110 Log *log) override {
1111 StreamString dump_stream;
1112
1113 const lldb::addr_t load_addr = process_address + m_offset;
1114
1115 dump_stream.Printf("0x%" PRIx64 ": EntityResultVariable\n", load_addr);
1116
1117 Status err;
1118
1120
1121 {
1122 dump_stream.PutCString("Pointer:\n");
1123
1124 DataBufferHeap data(m_size, 0);
1125
1126 map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
1127
1128 if (!err.Success()) {
1129 dump_stream.PutCString(" <could not be read>\n");
1130 } else {
1131 DataExtractor extractor(data.GetBytes(), data.GetByteSize(),
1132 map.GetByteOrder(), map.GetAddressByteSize());
1133
1134 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
1135 load_addr);
1136
1137 lldb::offset_t offset = 0;
1138
1139 ptr = extractor.GetAddress(&offset);
1140
1141 dump_stream.PutChar('\n');
1142 }
1143 }
1144
1146 dump_stream.PutCString("Points to process memory:\n");
1147 } else {
1148 dump_stream.PutCString("Temporary allocation:\n");
1149 }
1150
1151 if (ptr == LLDB_INVALID_ADDRESS) {
1152 dump_stream.PutCString(" <could not be be found>\n");
1153 } else {
1155
1158
1159 if (!err.Success()) {
1160 dump_stream.PutCString(" <could not be read>\n");
1161 } else {
1162 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
1163 load_addr);
1164
1165 dump_stream.PutChar('\n');
1166 }
1167 }
1168
1169 log->PutString(dump_stream.GetString());
1170 }
1171
1172 void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {
1174 Status free_error;
1175
1176 map.Free(m_temporary_allocation, free_error);
1177 }
1178
1181 }
1182
1183private:
1185 /// This is used both to control whether this result entity can (and should)
1186 /// track the value in inferior memory, as well as to control whether LLDB
1187 /// needs to allocate memory for the variable during materialization.
1190
1194};
1195
1197 bool is_program_reference,
1198 bool keep_in_memory,
1200 Status &err) {
1201 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1202 *iter = std::make_unique<EntityResultVariable>(type, is_program_reference,
1203 keep_in_memory, delegate);
1204 uint32_t ret = AddStructMember(**iter);
1205 (*iter)->SetOffset(ret);
1206 return ret;
1207}
1208
1210public:
1211 EntitySymbol(const Symbol &symbol) : Entity(), m_symbol(symbol) {
1212 // Hard-coding to maximum size of a symbol
1215 }
1216
1218 lldb::addr_t process_address, Status &err) override {
1220
1221 const lldb::addr_t load_addr = process_address + m_offset;
1222
1223 LLDB_LOG(log, "EntitySymbol::Materialize [address = {0}, m_symbol = {1}]",
1224 (uint64_t)load_addr, m_symbol.GetName());
1225
1226 const Address sym_address = m_symbol.GetAddress();
1227
1228 ExecutionContextScope *exe_scope = frame_sp.get();
1229 if (!exe_scope)
1230 exe_scope = map.GetBestExecutionContextScope();
1231
1232 lldb::TargetSP target_sp;
1233
1234 if (exe_scope)
1235 target_sp = map.GetBestExecutionContextScope()->CalculateTarget();
1236
1237 if (!target_sp) {
1239 "couldn't resolve symbol {0} because there is no target",
1240 m_symbol.GetName());
1241 return;
1242 }
1243
1244 lldb::addr_t resolved_address = sym_address.GetLoadAddress(target_sp.get());
1245
1246 if (resolved_address == LLDB_INVALID_ADDRESS)
1247 resolved_address = sym_address.GetFileAddress();
1248
1249 Status pointer_write_error;
1250
1251 map.WritePointerToMemory(load_addr, resolved_address, pointer_write_error);
1252
1253 if (!pointer_write_error.Success()) {
1255 "couldn't write the address of symbol {0}: {1}", m_symbol.GetName(),
1256 pointer_write_error.AsCString());
1257 return;
1258 }
1259 }
1260
1262 lldb::addr_t process_address, lldb::addr_t frame_top,
1263 lldb::addr_t frame_bottom, Status &err) override {
1265
1266 const lldb::addr_t load_addr = process_address + m_offset;
1267
1268 LLDB_LOG(log,
1269 "EntitySymbol::Dematerialize [address = {0:x}, m_symbol = {1}]",
1270 (uint64_t)load_addr, m_symbol.GetName());
1271
1272 // no work needs to be done
1273 }
1274
1275 void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
1276 Log *log) override {
1277 StreamString dump_stream;
1278
1279 Status err;
1280
1281 const lldb::addr_t load_addr = process_address + m_offset;
1282
1283 dump_stream.Format("{0:x}: EntitySymbol ({1})\n", load_addr,
1284 m_symbol.GetName());
1285
1286 {
1287 dump_stream.PutCString("Pointer:\n");
1288
1289 DataBufferHeap data(m_size, 0);
1290
1291 map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
1292
1293 if (!err.Success()) {
1294 dump_stream.PutCString(" <could not be read>\n");
1295 } else {
1296 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
1297 load_addr);
1298
1299 dump_stream.PutChar('\n');
1300 }
1301 }
1302
1303 log->PutString(dump_stream.GetString());
1304 }
1305
1306 void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}
1307
1308private:
1310};
1311
1312uint32_t Materializer::AddSymbol(const Symbol &symbol_sp, Status &err) {
1313 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1314 *iter = std::make_unique<EntitySymbol>(symbol_sp);
1315 uint32_t ret = AddStructMember(**iter);
1316 (*iter)->SetOffset(ret);
1317 return ret;
1318}
1319
1321public:
1322 EntityRegister(const RegisterInfo &register_info)
1323 : Entity(), m_register_info(register_info) {
1324 // Hard-coding alignment conservatively
1325 m_size = m_register_info.byte_size;
1326 m_alignment = m_register_info.byte_size;
1327 }
1328
1330 lldb::addr_t process_address, Status &err) override {
1332
1333 const lldb::addr_t load_addr = process_address + m_offset;
1334
1335 LLDB_LOGF(log,
1336 "EntityRegister::Materialize [address = 0x%" PRIx64
1337 ", m_register_info = %s]",
1338 (uint64_t)load_addr, m_register_info.name);
1339
1340 RegisterValue reg_value;
1341
1342 if (!frame_sp.get()) {
1344 "couldn't materialize register %s without a stack frame",
1345 m_register_info.name);
1346 return;
1347 }
1348
1349 lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
1350
1351 if (!reg_context_sp->ReadRegister(&m_register_info, reg_value)) {
1353 "couldn't read the value of register %s", m_register_info.name);
1354 return;
1355 }
1356
1357 if (reg_value.GetByteSize() != m_register_info.byte_size) {
1359 "data for register %s had size %llu but we expected %llu",
1360 m_register_info.name, (unsigned long long)reg_value.GetByteSize(),
1361 (unsigned long long)m_register_info.byte_size);
1362 return;
1363 }
1364
1365 lldb_private::DataBufferHeap buf(reg_value.GetByteSize(), 0);
1366 reg_value.GetAsMemoryData(m_register_info, buf.GetBytes(),
1367 buf.GetByteSize(), map.GetByteOrder(), err);
1368 if (!err.Success())
1369 return;
1370
1371 m_register_contents = std::make_shared<DataBufferHeap>(buf);
1372
1373 Status write_error;
1374
1375 map.WriteMemory(load_addr, buf.GetBytes(), reg_value.GetByteSize(),
1376 write_error);
1377
1378 if (!write_error.Success()) {
1380 "couldn't write the contents of register %s: %s",
1381 m_register_info.name, write_error.AsCString());
1382 return;
1383 }
1384 }
1385
1387 lldb::addr_t process_address, lldb::addr_t frame_top,
1388 lldb::addr_t frame_bottom, Status &err) override {
1390
1391 const lldb::addr_t load_addr = process_address + m_offset;
1392
1393 LLDB_LOGF(log,
1394 "EntityRegister::Dematerialize [address = 0x%" PRIx64
1395 ", m_register_info = %s]",
1396 (uint64_t)load_addr, m_register_info.name);
1397
1398 Status extract_error;
1399
1400 DataExtractor register_data;
1401
1402 if (!frame_sp.get()) {
1404 "couldn't dematerialize register %s without a stack frame",
1405 m_register_info.name);
1406 return;
1407 }
1408
1409 lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext();
1410
1411 map.GetMemoryData(register_data, load_addr, m_register_info.byte_size,
1412 extract_error);
1413
1414 if (!extract_error.Success()) {
1416 "couldn't get the data for register %s: %s", m_register_info.name,
1417 extract_error.AsCString());
1418 return;
1419 }
1420
1421 if (!memcmp(register_data.GetDataStart(), m_register_contents->GetBytes(),
1422 register_data.GetByteSize())) {
1423 // No write required, and in particular we avoid errors if the register
1424 // wasn't writable
1425
1426 m_register_contents.reset();
1427 return;
1428 }
1429
1430 m_register_contents.reset();
1431
1432 RegisterValue register_value(register_data.GetData(),
1433 register_data.GetByteOrder());
1434
1435 if (!reg_context_sp->WriteRegister(&m_register_info, register_value)) {
1437 "couldn't write the value of register %s", m_register_info.name);
1438 return;
1439 }
1440 }
1441
1442 void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address,
1443 Log *log) override {
1444 StreamString dump_stream;
1445
1446 Status err;
1447
1448 const lldb::addr_t load_addr = process_address + m_offset;
1449
1450 dump_stream.Printf("0x%" PRIx64 ": EntityRegister (%s)\n", load_addr,
1451 m_register_info.name);
1452
1453 {
1454 dump_stream.PutCString("Value:\n");
1455
1456 DataBufferHeap data(m_size, 0);
1457
1458 map.ReadMemory(data.GetBytes(), load_addr, m_size, err);
1459
1460 if (!err.Success()) {
1461 dump_stream.PutCString(" <could not be read>\n");
1462 } else {
1463 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16,
1464 load_addr);
1465
1466 dump_stream.PutChar('\n');
1467 }
1468 }
1469
1470 log->PutString(dump_stream.GetString());
1471 }
1472
1473 void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {}
1474
1475private:
1478};
1479
1480uint32_t Materializer::AddRegister(const RegisterInfo &register_info,
1481 Status &err) {
1482 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
1483 *iter = std::make_unique<EntityRegister>(register_info);
1484 uint32_t ret = AddStructMember(**iter);
1485 (*iter)->SetOffset(ret);
1486 return ret;
1487}
1488
1490 DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
1491
1492 if (dematerializer_sp)
1493 dematerializer_sp->Wipe();
1494}
1495
1498 lldb::addr_t process_address, Status &error) {
1499 ExecutionContextScope *exe_scope = frame_sp.get();
1500 if (!exe_scope)
1501 exe_scope = map.GetBestExecutionContextScope();
1502
1503 DematerializerSP dematerializer_sp = m_dematerializer_wp.lock();
1504
1505 if (dematerializer_sp) {
1506 error =
1507 Status::FromErrorString("Couldn't materialize: already materialized");
1508 }
1509
1510 DematerializerSP ret(
1511 new Dematerializer(*this, frame_sp, map, process_address));
1512
1513 if (!exe_scope) {
1514 error =
1515 Status::FromErrorString("Couldn't materialize: target doesn't exist");
1516 }
1517
1518 for (EntityUP &entity_up : m_entities) {
1519 entity_up->Materialize(frame_sp, map, process_address, error);
1520
1521 if (!error.Success())
1522 return DematerializerSP();
1523 }
1524
1525 if (Log *log = GetLog(LLDBLog::Expressions)) {
1526 LLDB_LOGF(
1527 log,
1528 "Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64
1529 ") materialized:",
1530 static_cast<void *>(frame_sp.get()), process_address);
1531 for (EntityUP &entity_up : m_entities)
1532 entity_up->DumpToLog(map, process_address, log);
1533 }
1534
1535 m_dematerializer_wp = ret;
1536
1537 return ret;
1538}
1539
1541 lldb::addr_t frame_bottom,
1542 lldb::addr_t frame_top) {
1543 lldb::StackFrameSP frame_sp;
1544
1545 lldb::ThreadSP thread_sp = m_thread_wp.lock();
1546 if (thread_sp)
1547 frame_sp = thread_sp->GetFrameWithStackID(m_stack_id);
1548
1549 ExecutionContextScope *exe_scope = frame_sp.get();
1550 if (!exe_scope)
1551 exe_scope = m_map->GetBestExecutionContextScope();
1552
1553 if (!IsValid()) {
1555 "Couldn't dematerialize: invalid dematerializer");
1556 }
1557
1558 if (!exe_scope) {
1559 error = Status::FromErrorString("Couldn't dematerialize: target is gone");
1560 } else {
1561 if (Log *log = GetLog(LLDBLog::Expressions)) {
1562 LLDB_LOGF(log,
1563 "Materializer::Dematerialize (frame_sp = %p, process_address "
1564 "= 0x%" PRIx64 ") about to dematerialize:",
1565 static_cast<void *>(frame_sp.get()), m_process_address);
1566 for (EntityUP &entity_up : m_materializer->m_entities)
1567 entity_up->DumpToLog(*m_map, m_process_address, log);
1568 }
1569
1570 for (EntityUP &entity_up : m_materializer->m_entities) {
1571 entity_up->Dematerialize(frame_sp, *m_map, m_process_address, frame_top,
1572 frame_bottom, error);
1573
1574 if (!error.Success())
1575 break;
1576 }
1577 }
1578
1579 Wipe();
1580}
1581
1583 if (!IsValid())
1584 return;
1585
1586 for (EntityUP &entity_up : m_materializer->m_entities) {
1587 entity_up->Wipe(*m_map, m_process_address);
1588 }
1589
1590 m_materializer = nullptr;
1591 m_map = nullptr;
1593}
1594
1596 default;
1598 default;
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition Log.h:375
#define LLDB_LOGF(log,...)
Definition Log.h:389
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
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.
virtual 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:164
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:214
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:293
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
Definition Status.cpp:194
static Status static Status FromErrorStringWithFormatv(const char *format, Args &&...args)
Definition Status.h:151
static Status FromError(llvm::Error error)
Avoid using this in new code. Migrate APIs to llvm::Expected instead.
Definition Status.cpp:136
bool Success() const
Test for success condition.
Definition Status.cpp:303
llvm::StringRef GetString() const
void Format(const char *format, Args &&... args)
Forwards the arguments to llvm::formatv and writes to the stream.
Definition Stream.h:370
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:134
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition Stream.cpp:63
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, ValueObjectManager *manager=nullptr)
These routines create ValueObjectConstResult ValueObjects from various data sources.
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:338
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.
std::string toString(FormatterBytecode::OpCodes op)
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),...