Materializer.cpp revision 353358
1//===-- Materializer.cpp ----------------------------------------*- C++ -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8 9#include "lldb/Expression/Materializer.h" 10#include "lldb/Core/DumpDataExtractor.h" 11#include "lldb/Core/ValueObjectConstResult.h" 12#include "lldb/Core/ValueObjectVariable.h" 13#include "lldb/Expression/ExpressionVariable.h" 14#include "lldb/Symbol/ClangASTContext.h" 15#include "lldb/Symbol/Symbol.h" 16#include "lldb/Symbol/Type.h" 17#include "lldb/Symbol/Variable.h" 18#include "lldb/Target/ExecutionContext.h" 19#include "lldb/Target/RegisterContext.h" 20#include "lldb/Target/StackFrame.h" 21#include "lldb/Target/Target.h" 22#include "lldb/Target/Thread.h" 23#include "lldb/Utility/Log.h" 24#include "lldb/Utility/RegisterValue.h" 25 26#include <memory> 27 28using namespace lldb_private; 29 30uint32_t Materializer::AddStructMember(Entity &entity) { 31 uint32_t size = entity.GetSize(); 32 uint32_t alignment = entity.GetAlignment(); 33 34 uint32_t ret; 35 36 if (m_current_offset == 0) 37 m_struct_alignment = alignment; 38 39 if (m_current_offset % alignment) 40 m_current_offset += (alignment - (m_current_offset % alignment)); 41 42 ret = m_current_offset; 43 44 m_current_offset += size; 45 46 return ret; 47} 48 49void Materializer::Entity::SetSizeAndAlignmentFromType(CompilerType &type) { 50 if (llvm::Optional<uint64_t> size = type.GetByteSize(nullptr)) 51 m_size = *size; 52 53 uint32_t bit_alignment = type.GetTypeBitAlign(); 54 55 if (bit_alignment % 8) { 56 bit_alignment += 8; 57 bit_alignment &= ~((uint32_t)0x111u); 58 } 59 60 m_alignment = bit_alignment / 8; 61} 62 63class EntityPersistentVariable : public Materializer::Entity { 64public: 65 EntityPersistentVariable(lldb::ExpressionVariableSP &persistent_variable_sp, 66 Materializer::PersistentVariableDelegate *delegate) 67 : Entity(), m_persistent_variable_sp(persistent_variable_sp), 68 m_delegate(delegate) { 69 // Hard-coding to maximum size of a pointer since persistent variables are 70 // materialized by reference 71 m_size = 8; 72 m_alignment = 8; 73 } 74 75 void MakeAllocation(IRMemoryMap &map, Status &err) { 76 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); 77 78 // Allocate a spare memory area to store the persistent variable's 79 // contents. 80 81 Status allocate_error; 82 const bool zero_memory = false; 83 84 lldb::addr_t mem = map.Malloc( 85 m_persistent_variable_sp->GetByteSize(), 8, 86 lldb::ePermissionsReadable | lldb::ePermissionsWritable, 87 IRMemoryMap::eAllocationPolicyMirror, zero_memory, allocate_error); 88 89 if (!allocate_error.Success()) { 90 err.SetErrorStringWithFormat( 91 "couldn't allocate a memory area to store %s: %s", 92 m_persistent_variable_sp->GetName().GetCString(), 93 allocate_error.AsCString()); 94 return; 95 } 96 97 if (log) 98 log->Printf("Allocated %s (0x%" PRIx64 ") successfully", 99 m_persistent_variable_sp->GetName().GetCString(), mem); 100 101 // Put the location of the spare memory into the live data of the 102 // ValueObject. 103 104 m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create( 105 map.GetBestExecutionContextScope(), 106 m_persistent_variable_sp->GetCompilerType(), 107 m_persistent_variable_sp->GetName(), mem, eAddressTypeLoad, 108 map.GetAddressByteSize()); 109 110 // Clear the flag if the variable will never be deallocated. 111 112 if (m_persistent_variable_sp->m_flags & 113 ExpressionVariable::EVKeepInTarget) { 114 Status leak_error; 115 map.Leak(mem, leak_error); 116 m_persistent_variable_sp->m_flags &= 117 ~ExpressionVariable::EVNeedsAllocation; 118 } 119 120 // Write the contents of the variable to the area. 121 122 Status write_error; 123 124 map.WriteMemory(mem, m_persistent_variable_sp->GetValueBytes(), 125 m_persistent_variable_sp->GetByteSize(), write_error); 126 127 if (!write_error.Success()) { 128 err.SetErrorStringWithFormat( 129 "couldn't write %s to the target: %s", 130 m_persistent_variable_sp->GetName().AsCString(), 131 write_error.AsCString()); 132 return; 133 } 134 } 135 136 void DestroyAllocation(IRMemoryMap &map, Status &err) { 137 Status deallocate_error; 138 139 map.Free((lldb::addr_t)m_persistent_variable_sp->m_live_sp->GetValue() 140 .GetScalar() 141 .ULongLong(), 142 deallocate_error); 143 144 m_persistent_variable_sp->m_live_sp.reset(); 145 146 if (!deallocate_error.Success()) { 147 err.SetErrorStringWithFormat( 148 "couldn't deallocate memory for %s: %s", 149 m_persistent_variable_sp->GetName().GetCString(), 150 deallocate_error.AsCString()); 151 } 152 } 153 154 void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, 155 lldb::addr_t process_address, Status &err) override { 156 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); 157 158 const lldb::addr_t load_addr = process_address + m_offset; 159 160 if (log) { 161 log->Printf("EntityPersistentVariable::Materialize [address = 0x%" PRIx64 162 ", m_name = %s, m_flags = 0x%hx]", 163 (uint64_t)load_addr, 164 m_persistent_variable_sp->GetName().AsCString(), 165 m_persistent_variable_sp->m_flags); 166 } 167 168 if (m_persistent_variable_sp->m_flags & 169 ExpressionVariable::EVNeedsAllocation) { 170 MakeAllocation(map, err); 171 m_persistent_variable_sp->m_flags |= 172 ExpressionVariable::EVIsLLDBAllocated; 173 174 if (!err.Success()) 175 return; 176 } 177 178 if ((m_persistent_variable_sp->m_flags & 179 ExpressionVariable::EVIsProgramReference && 180 m_persistent_variable_sp->m_live_sp) || 181 m_persistent_variable_sp->m_flags & 182 ExpressionVariable::EVIsLLDBAllocated) { 183 Status write_error; 184 185 map.WriteScalarToMemory( 186 load_addr, 187 m_persistent_variable_sp->m_live_sp->GetValue().GetScalar(), 188 map.GetAddressByteSize(), write_error); 189 190 if (!write_error.Success()) { 191 err.SetErrorStringWithFormat( 192 "couldn't write the location of %s to memory: %s", 193 m_persistent_variable_sp->GetName().AsCString(), 194 write_error.AsCString()); 195 } 196 } else { 197 err.SetErrorStringWithFormat( 198 "no materialization happened for persistent variable %s", 199 m_persistent_variable_sp->GetName().AsCString()); 200 return; 201 } 202 } 203 204 void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, 205 lldb::addr_t process_address, lldb::addr_t frame_top, 206 lldb::addr_t frame_bottom, Status &err) override { 207 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); 208 209 const lldb::addr_t load_addr = process_address + m_offset; 210 211 if (log) { 212 log->Printf( 213 "EntityPersistentVariable::Dematerialize [address = 0x%" PRIx64 214 ", m_name = %s, m_flags = 0x%hx]", 215 (uint64_t)process_address + m_offset, 216 m_persistent_variable_sp->GetName().AsCString(), 217 m_persistent_variable_sp->m_flags); 218 } 219 220 if (m_delegate) { 221 m_delegate->DidDematerialize(m_persistent_variable_sp); 222 } 223 224 if ((m_persistent_variable_sp->m_flags & 225 ExpressionVariable::EVIsLLDBAllocated) || 226 (m_persistent_variable_sp->m_flags & 227 ExpressionVariable::EVIsProgramReference)) { 228 if (m_persistent_variable_sp->m_flags & 229 ExpressionVariable::EVIsProgramReference && 230 !m_persistent_variable_sp->m_live_sp) { 231 // If the reference comes from the program, then the 232 // ClangExpressionVariable's live variable data hasn't been set up yet. 233 // Do this now. 234 235 lldb::addr_t location; 236 Status read_error; 237 238 map.ReadPointerFromMemory(&location, load_addr, read_error); 239 240 if (!read_error.Success()) { 241 err.SetErrorStringWithFormat( 242 "couldn't read the address of program-allocated variable %s: %s", 243 m_persistent_variable_sp->GetName().GetCString(), 244 read_error.AsCString()); 245 return; 246 } 247 248 m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create( 249 map.GetBestExecutionContextScope(), 250 m_persistent_variable_sp.get()->GetCompilerType(), 251 m_persistent_variable_sp->GetName(), location, eAddressTypeLoad, 252 m_persistent_variable_sp->GetByteSize()); 253 254 if (frame_top != LLDB_INVALID_ADDRESS && 255 frame_bottom != LLDB_INVALID_ADDRESS && location >= frame_bottom && 256 location <= frame_top) { 257 // If the variable is resident in the stack frame created by the 258 // expression, then it cannot be relied upon to stay around. We 259 // treat it as needing reallocation. 260 m_persistent_variable_sp->m_flags |= 261 ExpressionVariable::EVIsLLDBAllocated; 262 m_persistent_variable_sp->m_flags |= 263 ExpressionVariable::EVNeedsAllocation; 264 m_persistent_variable_sp->m_flags |= 265 ExpressionVariable::EVNeedsFreezeDry; 266 m_persistent_variable_sp->m_flags &= 267 ~ExpressionVariable::EVIsProgramReference; 268 } 269 } 270 271 lldb::addr_t mem = m_persistent_variable_sp->m_live_sp->GetValue() 272 .GetScalar() 273 .ULongLong(); 274 275 if (!m_persistent_variable_sp->m_live_sp) { 276 err.SetErrorStringWithFormat( 277 "couldn't find the memory area used to store %s", 278 m_persistent_variable_sp->GetName().GetCString()); 279 return; 280 } 281 282 if (m_persistent_variable_sp->m_live_sp->GetValue() 283 .GetValueAddressType() != eAddressTypeLoad) { 284 err.SetErrorStringWithFormat( 285 "the address of the memory area for %s is in an incorrect format", 286 m_persistent_variable_sp->GetName().GetCString()); 287 return; 288 } 289 290 if (m_persistent_variable_sp->m_flags & 291 ExpressionVariable::EVNeedsFreezeDry || 292 m_persistent_variable_sp->m_flags & 293 ExpressionVariable::EVKeepInTarget) { 294 if (log) 295 log->Printf( 296 "Dematerializing %s from 0x%" PRIx64 " (size = %llu)", 297 m_persistent_variable_sp->GetName().GetCString(), (uint64_t)mem, 298 (unsigned long long)m_persistent_variable_sp->GetByteSize()); 299 300 // Read the contents of the spare memory area 301 302 m_persistent_variable_sp->ValueUpdated(); 303 304 Status read_error; 305 306 map.ReadMemory(m_persistent_variable_sp->GetValueBytes(), mem, 307 m_persistent_variable_sp->GetByteSize(), read_error); 308 309 if (!read_error.Success()) { 310 err.SetErrorStringWithFormat( 311 "couldn't read the contents of %s from memory: %s", 312 m_persistent_variable_sp->GetName().GetCString(), 313 read_error.AsCString()); 314 return; 315 } 316 317 m_persistent_variable_sp->m_flags &= 318 ~ExpressionVariable::EVNeedsFreezeDry; 319 } 320 } else { 321 err.SetErrorStringWithFormat( 322 "no dematerialization happened for persistent variable %s", 323 m_persistent_variable_sp->GetName().AsCString()); 324 return; 325 } 326 327 lldb::ProcessSP process_sp = 328 map.GetBestExecutionContextScope()->CalculateProcess(); 329 if (!process_sp || !process_sp->CanJIT()) { 330 // Allocations are not persistent so persistent variables cannot stay 331 // materialized. 332 333 m_persistent_variable_sp->m_flags |= 334 ExpressionVariable::EVNeedsAllocation; 335 336 DestroyAllocation(map, err); 337 if (!err.Success()) 338 return; 339 } else if (m_persistent_variable_sp->m_flags & 340 ExpressionVariable::EVNeedsAllocation && 341 !(m_persistent_variable_sp->m_flags & 342 ExpressionVariable::EVKeepInTarget)) { 343 DestroyAllocation(map, err); 344 if (!err.Success()) 345 return; 346 } 347 } 348 349 void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, 350 Log *log) override { 351 StreamString dump_stream; 352 353 Status err; 354 355 const lldb::addr_t load_addr = process_address + m_offset; 356 357 dump_stream.Printf("0x%" PRIx64 ": EntityPersistentVariable (%s)\n", 358 load_addr, 359 m_persistent_variable_sp->GetName().AsCString()); 360 361 { 362 dump_stream.Printf("Pointer:\n"); 363 364 DataBufferHeap data(m_size, 0); 365 366 map.ReadMemory(data.GetBytes(), load_addr, m_size, err); 367 368 if (!err.Success()) { 369 dump_stream.Printf(" <could not be read>\n"); 370 } else { 371 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, 372 load_addr); 373 374 dump_stream.PutChar('\n'); 375 } 376 } 377 378 { 379 dump_stream.Printf("Target:\n"); 380 381 lldb::addr_t target_address; 382 383 map.ReadPointerFromMemory(&target_address, load_addr, err); 384 385 if (!err.Success()) { 386 dump_stream.Printf(" <could not be read>\n"); 387 } else { 388 DataBufferHeap data(m_persistent_variable_sp->GetByteSize(), 0); 389 390 map.ReadMemory(data.GetBytes(), target_address, 391 m_persistent_variable_sp->GetByteSize(), err); 392 393 if (!err.Success()) { 394 dump_stream.Printf(" <could not be read>\n"); 395 } else { 396 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, 397 target_address); 398 399 dump_stream.PutChar('\n'); 400 } 401 } 402 } 403 404 log->PutString(dump_stream.GetString()); 405 } 406 407 void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {} 408 409private: 410 lldb::ExpressionVariableSP m_persistent_variable_sp; 411 Materializer::PersistentVariableDelegate *m_delegate; 412}; 413 414uint32_t Materializer::AddPersistentVariable( 415 lldb::ExpressionVariableSP &persistent_variable_sp, 416 PersistentVariableDelegate *delegate, Status &err) { 417 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); 418 iter->reset(new EntityPersistentVariable(persistent_variable_sp, delegate)); 419 uint32_t ret = AddStructMember(**iter); 420 (*iter)->SetOffset(ret); 421 return ret; 422} 423 424class EntityVariable : public Materializer::Entity { 425public: 426 EntityVariable(lldb::VariableSP &variable_sp) 427 : Entity(), m_variable_sp(variable_sp), m_is_reference(false), 428 m_temporary_allocation(LLDB_INVALID_ADDRESS), 429 m_temporary_allocation_size(0) { 430 // Hard-coding to maximum size of a pointer since all variables are 431 // materialized by reference 432 m_size = 8; 433 m_alignment = 8; 434 m_is_reference = 435 m_variable_sp->GetType()->GetForwardCompilerType().IsReferenceType(); 436 } 437 438 void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, 439 lldb::addr_t process_address, Status &err) override { 440 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); 441 442 const lldb::addr_t load_addr = process_address + m_offset; 443 if (log) { 444 log->Printf("EntityVariable::Materialize [address = 0x%" PRIx64 445 ", m_variable_sp = %s]", 446 (uint64_t)load_addr, m_variable_sp->GetName().AsCString()); 447 } 448 449 ExecutionContextScope *scope = frame_sp.get(); 450 451 if (!scope) 452 scope = map.GetBestExecutionContextScope(); 453 454 lldb::ValueObjectSP valobj_sp = 455 ValueObjectVariable::Create(scope, m_variable_sp); 456 457 if (!valobj_sp) { 458 err.SetErrorStringWithFormat( 459 "couldn't get a value object for variable %s", 460 m_variable_sp->GetName().AsCString()); 461 return; 462 } 463 464 Status valobj_error = valobj_sp->GetError(); 465 466 if (valobj_error.Fail()) { 467 err.SetErrorStringWithFormat("couldn't get the value of variable %s: %s", 468 m_variable_sp->GetName().AsCString(), 469 valobj_error.AsCString()); 470 return; 471 } 472 473 if (m_is_reference) { 474 DataExtractor valobj_extractor; 475 Status extract_error; 476 valobj_sp->GetData(valobj_extractor, extract_error); 477 478 if (!extract_error.Success()) { 479 err.SetErrorStringWithFormat( 480 "couldn't read contents of reference variable %s: %s", 481 m_variable_sp->GetName().AsCString(), extract_error.AsCString()); 482 return; 483 } 484 485 lldb::offset_t offset = 0; 486 lldb::addr_t reference_addr = valobj_extractor.GetAddress(&offset); 487 488 Status write_error; 489 map.WritePointerToMemory(load_addr, reference_addr, write_error); 490 491 if (!write_error.Success()) { 492 err.SetErrorStringWithFormat("couldn't write the contents of reference " 493 "variable %s to memory: %s", 494 m_variable_sp->GetName().AsCString(), 495 write_error.AsCString()); 496 return; 497 } 498 } else { 499 AddressType address_type = eAddressTypeInvalid; 500 const bool scalar_is_load_address = false; 501 lldb::addr_t addr_of_valobj = 502 valobj_sp->GetAddressOf(scalar_is_load_address, &address_type); 503 if (addr_of_valobj != LLDB_INVALID_ADDRESS) { 504 Status write_error; 505 map.WritePointerToMemory(load_addr, addr_of_valobj, write_error); 506 507 if (!write_error.Success()) { 508 err.SetErrorStringWithFormat( 509 "couldn't write the address of variable %s to memory: %s", 510 m_variable_sp->GetName().AsCString(), write_error.AsCString()); 511 return; 512 } 513 } else { 514 DataExtractor data; 515 Status extract_error; 516 valobj_sp->GetData(data, extract_error); 517 if (!extract_error.Success()) { 518 err.SetErrorStringWithFormat("couldn't get the value of %s: %s", 519 m_variable_sp->GetName().AsCString(), 520 extract_error.AsCString()); 521 return; 522 } 523 524 if (m_temporary_allocation != LLDB_INVALID_ADDRESS) { 525 err.SetErrorStringWithFormat( 526 "trying to create a temporary region for %s but one exists", 527 m_variable_sp->GetName().AsCString()); 528 return; 529 } 530 531 if (data.GetByteSize() < m_variable_sp->GetType()->GetByteSize()) { 532 if (data.GetByteSize() == 0 && 533 !m_variable_sp->LocationExpression().IsValid()) { 534 err.SetErrorStringWithFormat("the variable '%s' has no location, " 535 "it may have been optimized out", 536 m_variable_sp->GetName().AsCString()); 537 } else { 538 err.SetErrorStringWithFormat( 539 "size of variable %s (%" PRIu64 540 ") is larger than the ValueObject's size (%" PRIu64 ")", 541 m_variable_sp->GetName().AsCString(), 542 m_variable_sp->GetType()->GetByteSize().getValueOr(0), 543 data.GetByteSize()); 544 } 545 return; 546 } 547 548 size_t bit_align = 549 m_variable_sp->GetType()->GetLayoutCompilerType().GetTypeBitAlign(); 550 size_t byte_align = (bit_align + 7) / 8; 551 552 if (!byte_align) 553 byte_align = 1; 554 555 Status alloc_error; 556 const bool zero_memory = false; 557 558 m_temporary_allocation = map.Malloc( 559 data.GetByteSize(), byte_align, 560 lldb::ePermissionsReadable | lldb::ePermissionsWritable, 561 IRMemoryMap::eAllocationPolicyMirror, zero_memory, alloc_error); 562 563 m_temporary_allocation_size = data.GetByteSize(); 564 565 m_original_data = std::make_shared<DataBufferHeap>(data.GetDataStart(), 566 data.GetByteSize()); 567 568 if (!alloc_error.Success()) { 569 err.SetErrorStringWithFormat( 570 "couldn't allocate a temporary region for %s: %s", 571 m_variable_sp->GetName().AsCString(), alloc_error.AsCString()); 572 return; 573 } 574 575 Status write_error; 576 577 map.WriteMemory(m_temporary_allocation, data.GetDataStart(), 578 data.GetByteSize(), write_error); 579 580 if (!write_error.Success()) { 581 err.SetErrorStringWithFormat( 582 "couldn't write to the temporary region for %s: %s", 583 m_variable_sp->GetName().AsCString(), write_error.AsCString()); 584 return; 585 } 586 587 Status pointer_write_error; 588 589 map.WritePointerToMemory(load_addr, m_temporary_allocation, 590 pointer_write_error); 591 592 if (!pointer_write_error.Success()) { 593 err.SetErrorStringWithFormat( 594 "couldn't write the address of the temporary region for %s: %s", 595 m_variable_sp->GetName().AsCString(), 596 pointer_write_error.AsCString()); 597 } 598 } 599 } 600 } 601 602 void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, 603 lldb::addr_t process_address, lldb::addr_t frame_top, 604 lldb::addr_t frame_bottom, Status &err) override { 605 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); 606 607 const lldb::addr_t load_addr = process_address + m_offset; 608 if (log) { 609 log->Printf("EntityVariable::Dematerialize [address = 0x%" PRIx64 610 ", m_variable_sp = %s]", 611 (uint64_t)load_addr, m_variable_sp->GetName().AsCString()); 612 } 613 614 if (m_temporary_allocation != LLDB_INVALID_ADDRESS) { 615 ExecutionContextScope *scope = frame_sp.get(); 616 617 if (!scope) 618 scope = map.GetBestExecutionContextScope(); 619 620 lldb::ValueObjectSP valobj_sp = 621 ValueObjectVariable::Create(scope, m_variable_sp); 622 623 if (!valobj_sp) { 624 err.SetErrorStringWithFormat( 625 "couldn't get a value object for variable %s", 626 m_variable_sp->GetName().AsCString()); 627 return; 628 } 629 630 lldb_private::DataExtractor data; 631 632 Status extract_error; 633 634 map.GetMemoryData(data, m_temporary_allocation, valobj_sp->GetByteSize(), 635 extract_error); 636 637 if (!extract_error.Success()) { 638 err.SetErrorStringWithFormat("couldn't get the data for variable %s", 639 m_variable_sp->GetName().AsCString()); 640 return; 641 } 642 643 bool actually_write = true; 644 645 if (m_original_data) { 646 if ((data.GetByteSize() == m_original_data->GetByteSize()) && 647 !memcmp(m_original_data->GetBytes(), data.GetDataStart(), 648 data.GetByteSize())) { 649 actually_write = false; 650 } 651 } 652 653 Status set_error; 654 655 if (actually_write) { 656 valobj_sp->SetData(data, set_error); 657 658 if (!set_error.Success()) { 659 err.SetErrorStringWithFormat( 660 "couldn't write the new contents of %s back into the variable", 661 m_variable_sp->GetName().AsCString()); 662 return; 663 } 664 } 665 666 Status free_error; 667 668 map.Free(m_temporary_allocation, free_error); 669 670 if (!free_error.Success()) { 671 err.SetErrorStringWithFormat( 672 "couldn't free the temporary region for %s: %s", 673 m_variable_sp->GetName().AsCString(), free_error.AsCString()); 674 return; 675 } 676 677 m_original_data.reset(); 678 m_temporary_allocation = LLDB_INVALID_ADDRESS; 679 m_temporary_allocation_size = 0; 680 } 681 } 682 683 void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, 684 Log *log) override { 685 StreamString dump_stream; 686 687 const lldb::addr_t load_addr = process_address + m_offset; 688 dump_stream.Printf("0x%" PRIx64 ": EntityVariable\n", load_addr); 689 690 Status err; 691 692 lldb::addr_t ptr = LLDB_INVALID_ADDRESS; 693 694 { 695 dump_stream.Printf("Pointer:\n"); 696 697 DataBufferHeap data(m_size, 0); 698 699 map.ReadMemory(data.GetBytes(), load_addr, m_size, err); 700 701 if (!err.Success()) { 702 dump_stream.Printf(" <could not be read>\n"); 703 } else { 704 DataExtractor extractor(data.GetBytes(), data.GetByteSize(), 705 map.GetByteOrder(), map.GetAddressByteSize()); 706 707 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, 708 load_addr); 709 710 lldb::offset_t offset; 711 712 ptr = extractor.GetPointer(&offset); 713 714 dump_stream.PutChar('\n'); 715 } 716 } 717 718 if (m_temporary_allocation == LLDB_INVALID_ADDRESS) { 719 dump_stream.Printf("Points to process memory:\n"); 720 } else { 721 dump_stream.Printf("Temporary allocation:\n"); 722 } 723 724 if (ptr == LLDB_INVALID_ADDRESS) { 725 dump_stream.Printf(" <could not be be found>\n"); 726 } else { 727 DataBufferHeap data(m_temporary_allocation_size, 0); 728 729 map.ReadMemory(data.GetBytes(), m_temporary_allocation, 730 m_temporary_allocation_size, err); 731 732 if (!err.Success()) { 733 dump_stream.Printf(" <could not be read>\n"); 734 } else { 735 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, 736 load_addr); 737 738 dump_stream.PutChar('\n'); 739 } 740 } 741 742 log->PutString(dump_stream.GetString()); 743 } 744 745 void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override { 746 if (m_temporary_allocation != LLDB_INVALID_ADDRESS) { 747 Status free_error; 748 749 map.Free(m_temporary_allocation, free_error); 750 751 m_temporary_allocation = LLDB_INVALID_ADDRESS; 752 m_temporary_allocation_size = 0; 753 } 754 } 755 756private: 757 lldb::VariableSP m_variable_sp; 758 bool m_is_reference; 759 lldb::addr_t m_temporary_allocation; 760 size_t m_temporary_allocation_size; 761 lldb::DataBufferSP m_original_data; 762}; 763 764uint32_t Materializer::AddVariable(lldb::VariableSP &variable_sp, Status &err) { 765 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); 766 iter->reset(new EntityVariable(variable_sp)); 767 uint32_t ret = AddStructMember(**iter); 768 (*iter)->SetOffset(ret); 769 return ret; 770} 771 772class EntityResultVariable : public Materializer::Entity { 773public: 774 EntityResultVariable(const CompilerType &type, bool is_program_reference, 775 bool keep_in_memory, 776 Materializer::PersistentVariableDelegate *delegate) 777 : Entity(), m_type(type), m_is_program_reference(is_program_reference), 778 m_keep_in_memory(keep_in_memory), 779 m_temporary_allocation(LLDB_INVALID_ADDRESS), 780 m_temporary_allocation_size(0), m_delegate(delegate) { 781 // Hard-coding to maximum size of a pointer since all results are 782 // materialized by reference 783 m_size = 8; 784 m_alignment = 8; 785 } 786 787 void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, 788 lldb::addr_t process_address, Status &err) override { 789 if (!m_is_program_reference) { 790 if (m_temporary_allocation != LLDB_INVALID_ADDRESS) { 791 err.SetErrorString("Trying to create a temporary region for the result " 792 "but one exists"); 793 return; 794 } 795 796 const lldb::addr_t load_addr = process_address + m_offset; 797 798 ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope(); 799 800 llvm::Optional<uint64_t> byte_size = m_type.GetByteSize(exe_scope); 801 if (!byte_size) { 802 err.SetErrorString("can't get size of type"); 803 return; 804 } 805 size_t bit_align = m_type.GetTypeBitAlign(); 806 size_t byte_align = (bit_align + 7) / 8; 807 808 if (!byte_align) 809 byte_align = 1; 810 811 Status alloc_error; 812 const bool zero_memory = true; 813 814 m_temporary_allocation = map.Malloc( 815 *byte_size, byte_align, 816 lldb::ePermissionsReadable | lldb::ePermissionsWritable, 817 IRMemoryMap::eAllocationPolicyMirror, zero_memory, alloc_error); 818 m_temporary_allocation_size = *byte_size; 819 820 if (!alloc_error.Success()) { 821 err.SetErrorStringWithFormat( 822 "couldn't allocate a temporary region for the result: %s", 823 alloc_error.AsCString()); 824 return; 825 } 826 827 Status pointer_write_error; 828 829 map.WritePointerToMemory(load_addr, m_temporary_allocation, 830 pointer_write_error); 831 832 if (!pointer_write_error.Success()) { 833 err.SetErrorStringWithFormat("couldn't write the address of the " 834 "temporary region for the result: %s", 835 pointer_write_error.AsCString()); 836 } 837 } 838 } 839 840 void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, 841 lldb::addr_t process_address, lldb::addr_t frame_top, 842 lldb::addr_t frame_bottom, Status &err) override { 843 err.Clear(); 844 845 ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope(); 846 847 if (!exe_scope) { 848 err.SetErrorString("Couldn't dematerialize a result variable: invalid " 849 "execution context scope"); 850 return; 851 } 852 853 lldb::addr_t address; 854 Status read_error; 855 const lldb::addr_t load_addr = process_address + m_offset; 856 857 map.ReadPointerFromMemory(&address, load_addr, read_error); 858 859 if (!read_error.Success()) { 860 err.SetErrorString("Couldn't dematerialize a result variable: couldn't " 861 "read its address"); 862 return; 863 } 864 865 lldb::TargetSP target_sp = exe_scope->CalculateTarget(); 866 867 if (!target_sp) { 868 err.SetErrorString("Couldn't dematerialize a result variable: no target"); 869 return; 870 } 871 872 Status type_system_error; 873 TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage( 874 &type_system_error, m_type.GetMinimumLanguage()); 875 876 if (!type_system) { 877 err.SetErrorStringWithFormat("Couldn't dematerialize a result variable: " 878 "couldn't get the corresponding type " 879 "system: %s", 880 type_system_error.AsCString()); 881 return; 882 } 883 884 PersistentExpressionState *persistent_state = 885 type_system->GetPersistentExpressionState(); 886 887 if (!persistent_state) { 888 err.SetErrorString("Couldn't dematerialize a result variable: " 889 "corresponding type system doesn't handle persistent " 890 "variables"); 891 return; 892 } 893 894 ConstString name = 895 m_delegate 896 ? m_delegate->GetName() 897 : persistent_state->GetNextPersistentVariableName( 898 *target_sp, persistent_state->GetPersistentVariablePrefix()); 899 900 lldb::ExpressionVariableSP ret = persistent_state->CreatePersistentVariable( 901 exe_scope, name, m_type, map.GetByteOrder(), map.GetAddressByteSize()); 902 903 if (!ret) { 904 err.SetErrorStringWithFormat("couldn't dematerialize a result variable: " 905 "failed to make persistent variable %s", 906 name.AsCString()); 907 return; 908 } 909 910 lldb::ProcessSP process_sp = 911 map.GetBestExecutionContextScope()->CalculateProcess(); 912 913 if (m_delegate) { 914 m_delegate->DidDematerialize(ret); 915 } 916 917 bool can_persist = 918 (m_is_program_reference && process_sp && process_sp->CanJIT() && 919 !(address >= frame_bottom && address < frame_top)); 920 921 if (can_persist && m_keep_in_memory) { 922 ret->m_live_sp = ValueObjectConstResult::Create(exe_scope, m_type, name, 923 address, eAddressTypeLoad, 924 map.GetAddressByteSize()); 925 } 926 927 ret->ValueUpdated(); 928 929 const size_t pvar_byte_size = ret->GetByteSize(); 930 uint8_t *pvar_data = ret->GetValueBytes(); 931 932 map.ReadMemory(pvar_data, address, pvar_byte_size, read_error); 933 934 if (!read_error.Success()) { 935 err.SetErrorString( 936 "Couldn't dematerialize a result variable: couldn't read its memory"); 937 return; 938 } 939 940 if (!can_persist || !m_keep_in_memory) { 941 ret->m_flags |= ExpressionVariable::EVNeedsAllocation; 942 943 if (m_temporary_allocation != LLDB_INVALID_ADDRESS) { 944 Status free_error; 945 map.Free(m_temporary_allocation, free_error); 946 } 947 } else { 948 ret->m_flags |= ExpressionVariable::EVIsLLDBAllocated; 949 } 950 951 m_temporary_allocation = LLDB_INVALID_ADDRESS; 952 m_temporary_allocation_size = 0; 953 } 954 955 void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, 956 Log *log) override { 957 StreamString dump_stream; 958 959 const lldb::addr_t load_addr = process_address + m_offset; 960 961 dump_stream.Printf("0x%" PRIx64 ": EntityResultVariable\n", load_addr); 962 963 Status err; 964 965 lldb::addr_t ptr = LLDB_INVALID_ADDRESS; 966 967 { 968 dump_stream.Printf("Pointer:\n"); 969 970 DataBufferHeap data(m_size, 0); 971 972 map.ReadMemory(data.GetBytes(), load_addr, m_size, err); 973 974 if (!err.Success()) { 975 dump_stream.Printf(" <could not be read>\n"); 976 } else { 977 DataExtractor extractor(data.GetBytes(), data.GetByteSize(), 978 map.GetByteOrder(), map.GetAddressByteSize()); 979 980 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, 981 load_addr); 982 983 lldb::offset_t offset; 984 985 ptr = extractor.GetPointer(&offset); 986 987 dump_stream.PutChar('\n'); 988 } 989 } 990 991 if (m_temporary_allocation == LLDB_INVALID_ADDRESS) { 992 dump_stream.Printf("Points to process memory:\n"); 993 } else { 994 dump_stream.Printf("Temporary allocation:\n"); 995 } 996 997 if (ptr == LLDB_INVALID_ADDRESS) { 998 dump_stream.Printf(" <could not be be found>\n"); 999 } else { 1000 DataBufferHeap data(m_temporary_allocation_size, 0); 1001 1002 map.ReadMemory(data.GetBytes(), m_temporary_allocation, 1003 m_temporary_allocation_size, err); 1004 1005 if (!err.Success()) { 1006 dump_stream.Printf(" <could not be read>\n"); 1007 } else { 1008 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, 1009 load_addr); 1010 1011 dump_stream.PutChar('\n'); 1012 } 1013 } 1014 1015 log->PutString(dump_stream.GetString()); 1016 } 1017 1018 void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override { 1019 if (!m_keep_in_memory && m_temporary_allocation != LLDB_INVALID_ADDRESS) { 1020 Status free_error; 1021 1022 map.Free(m_temporary_allocation, free_error); 1023 } 1024 1025 m_temporary_allocation = LLDB_INVALID_ADDRESS; 1026 m_temporary_allocation_size = 0; 1027 } 1028 1029private: 1030 CompilerType m_type; 1031 bool m_is_program_reference; 1032 bool m_keep_in_memory; 1033 1034 lldb::addr_t m_temporary_allocation; 1035 size_t m_temporary_allocation_size; 1036 Materializer::PersistentVariableDelegate *m_delegate; 1037}; 1038 1039uint32_t Materializer::AddResultVariable(const CompilerType &type, 1040 bool is_program_reference, 1041 bool keep_in_memory, 1042 PersistentVariableDelegate *delegate, 1043 Status &err) { 1044 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); 1045 iter->reset(new EntityResultVariable(type, is_program_reference, 1046 keep_in_memory, delegate)); 1047 uint32_t ret = AddStructMember(**iter); 1048 (*iter)->SetOffset(ret); 1049 return ret; 1050} 1051 1052class EntitySymbol : public Materializer::Entity { 1053public: 1054 EntitySymbol(const Symbol &symbol) : Entity(), m_symbol(symbol) { 1055 // Hard-coding to maximum size of a symbol 1056 m_size = 8; 1057 m_alignment = 8; 1058 } 1059 1060 void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, 1061 lldb::addr_t process_address, Status &err) override { 1062 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); 1063 1064 const lldb::addr_t load_addr = process_address + m_offset; 1065 1066 if (log) { 1067 log->Printf("EntitySymbol::Materialize [address = 0x%" PRIx64 1068 ", m_symbol = %s]", 1069 (uint64_t)load_addr, m_symbol.GetName().AsCString()); 1070 } 1071 1072 const Address sym_address = m_symbol.GetAddress(); 1073 1074 ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope(); 1075 1076 lldb::TargetSP target_sp; 1077 1078 if (exe_scope) 1079 target_sp = map.GetBestExecutionContextScope()->CalculateTarget(); 1080 1081 if (!target_sp) { 1082 err.SetErrorStringWithFormat( 1083 "couldn't resolve symbol %s because there is no target", 1084 m_symbol.GetName().AsCString()); 1085 return; 1086 } 1087 1088 lldb::addr_t resolved_address = sym_address.GetLoadAddress(target_sp.get()); 1089 1090 if (resolved_address == LLDB_INVALID_ADDRESS) 1091 resolved_address = sym_address.GetFileAddress(); 1092 1093 Status pointer_write_error; 1094 1095 map.WritePointerToMemory(load_addr, resolved_address, pointer_write_error); 1096 1097 if (!pointer_write_error.Success()) { 1098 err.SetErrorStringWithFormat( 1099 "couldn't write the address of symbol %s: %s", 1100 m_symbol.GetName().AsCString(), pointer_write_error.AsCString()); 1101 return; 1102 } 1103 } 1104 1105 void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, 1106 lldb::addr_t process_address, lldb::addr_t frame_top, 1107 lldb::addr_t frame_bottom, Status &err) override { 1108 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); 1109 1110 const lldb::addr_t load_addr = process_address + m_offset; 1111 1112 if (log) { 1113 log->Printf("EntitySymbol::Dematerialize [address = 0x%" PRIx64 1114 ", m_symbol = %s]", 1115 (uint64_t)load_addr, m_symbol.GetName().AsCString()); 1116 } 1117 1118 // no work needs to be done 1119 } 1120 1121 void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, 1122 Log *log) override { 1123 StreamString dump_stream; 1124 1125 Status err; 1126 1127 const lldb::addr_t load_addr = process_address + m_offset; 1128 1129 dump_stream.Printf("0x%" PRIx64 ": EntitySymbol (%s)\n", load_addr, 1130 m_symbol.GetName().AsCString()); 1131 1132 { 1133 dump_stream.Printf("Pointer:\n"); 1134 1135 DataBufferHeap data(m_size, 0); 1136 1137 map.ReadMemory(data.GetBytes(), load_addr, m_size, err); 1138 1139 if (!err.Success()) { 1140 dump_stream.Printf(" <could not be read>\n"); 1141 } else { 1142 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, 1143 load_addr); 1144 1145 dump_stream.PutChar('\n'); 1146 } 1147 } 1148 1149 log->PutString(dump_stream.GetString()); 1150 } 1151 1152 void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {} 1153 1154private: 1155 Symbol m_symbol; 1156}; 1157 1158uint32_t Materializer::AddSymbol(const Symbol &symbol_sp, Status &err) { 1159 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); 1160 iter->reset(new EntitySymbol(symbol_sp)); 1161 uint32_t ret = AddStructMember(**iter); 1162 (*iter)->SetOffset(ret); 1163 return ret; 1164} 1165 1166class EntityRegister : public Materializer::Entity { 1167public: 1168 EntityRegister(const RegisterInfo ®ister_info) 1169 : Entity(), m_register_info(register_info) { 1170 // Hard-coding alignment conservatively 1171 m_size = m_register_info.byte_size; 1172 m_alignment = m_register_info.byte_size; 1173 } 1174 1175 void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, 1176 lldb::addr_t process_address, Status &err) override { 1177 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); 1178 1179 const lldb::addr_t load_addr = process_address + m_offset; 1180 1181 if (log) { 1182 log->Printf("EntityRegister::Materialize [address = 0x%" PRIx64 1183 ", m_register_info = %s]", 1184 (uint64_t)load_addr, m_register_info.name); 1185 } 1186 1187 RegisterValue reg_value; 1188 1189 if (!frame_sp.get()) { 1190 err.SetErrorStringWithFormat( 1191 "couldn't materialize register %s without a stack frame", 1192 m_register_info.name); 1193 return; 1194 } 1195 1196 lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext(); 1197 1198 if (!reg_context_sp->ReadRegister(&m_register_info, reg_value)) { 1199 err.SetErrorStringWithFormat("couldn't read the value of register %s", 1200 m_register_info.name); 1201 return; 1202 } 1203 1204 DataExtractor register_data; 1205 1206 if (!reg_value.GetData(register_data)) { 1207 err.SetErrorStringWithFormat("couldn't get the data for register %s", 1208 m_register_info.name); 1209 return; 1210 } 1211 1212 if (register_data.GetByteSize() != m_register_info.byte_size) { 1213 err.SetErrorStringWithFormat( 1214 "data for register %s had size %llu but we expected %llu", 1215 m_register_info.name, (unsigned long long)register_data.GetByteSize(), 1216 (unsigned long long)m_register_info.byte_size); 1217 return; 1218 } 1219 1220 m_register_contents = std::make_shared<DataBufferHeap>( 1221 register_data.GetDataStart(), register_data.GetByteSize()); 1222 1223 Status write_error; 1224 1225 map.WriteMemory(load_addr, register_data.GetDataStart(), 1226 register_data.GetByteSize(), write_error); 1227 1228 if (!write_error.Success()) { 1229 err.SetErrorStringWithFormat( 1230 "couldn't write the contents of register %s: %s", 1231 m_register_info.name, write_error.AsCString()); 1232 return; 1233 } 1234 } 1235 1236 void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, 1237 lldb::addr_t process_address, lldb::addr_t frame_top, 1238 lldb::addr_t frame_bottom, Status &err) override { 1239 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); 1240 1241 const lldb::addr_t load_addr = process_address + m_offset; 1242 1243 if (log) { 1244 log->Printf("EntityRegister::Dematerialize [address = 0x%" PRIx64 1245 ", m_register_info = %s]", 1246 (uint64_t)load_addr, m_register_info.name); 1247 } 1248 1249 Status extract_error; 1250 1251 DataExtractor register_data; 1252 1253 if (!frame_sp.get()) { 1254 err.SetErrorStringWithFormat( 1255 "couldn't dematerialize register %s without a stack frame", 1256 m_register_info.name); 1257 return; 1258 } 1259 1260 lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext(); 1261 1262 map.GetMemoryData(register_data, load_addr, m_register_info.byte_size, 1263 extract_error); 1264 1265 if (!extract_error.Success()) { 1266 err.SetErrorStringWithFormat("couldn't get the data for register %s: %s", 1267 m_register_info.name, 1268 extract_error.AsCString()); 1269 return; 1270 } 1271 1272 if (!memcmp(register_data.GetDataStart(), m_register_contents->GetBytes(), 1273 register_data.GetByteSize())) { 1274 // No write required, and in particular we avoid errors if the register 1275 // wasn't writable 1276 1277 m_register_contents.reset(); 1278 return; 1279 } 1280 1281 m_register_contents.reset(); 1282 1283 RegisterValue register_value( 1284 const_cast<uint8_t *>(register_data.GetDataStart()), 1285 register_data.GetByteSize(), register_data.GetByteOrder()); 1286 1287 if (!reg_context_sp->WriteRegister(&m_register_info, register_value)) { 1288 err.SetErrorStringWithFormat("couldn't write the value of register %s", 1289 m_register_info.name); 1290 return; 1291 } 1292 } 1293 1294 void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, 1295 Log *log) override { 1296 StreamString dump_stream; 1297 1298 Status err; 1299 1300 const lldb::addr_t load_addr = process_address + m_offset; 1301 1302 dump_stream.Printf("0x%" PRIx64 ": EntityRegister (%s)\n", load_addr, 1303 m_register_info.name); 1304 1305 { 1306 dump_stream.Printf("Value:\n"); 1307 1308 DataBufferHeap data(m_size, 0); 1309 1310 map.ReadMemory(data.GetBytes(), load_addr, m_size, err); 1311 1312 if (!err.Success()) { 1313 dump_stream.Printf(" <could not be read>\n"); 1314 } else { 1315 DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, 1316 load_addr); 1317 1318 dump_stream.PutChar('\n'); 1319 } 1320 } 1321 1322 log->PutString(dump_stream.GetString()); 1323 } 1324 1325 void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override {} 1326 1327private: 1328 RegisterInfo m_register_info; 1329 lldb::DataBufferSP m_register_contents; 1330}; 1331 1332uint32_t Materializer::AddRegister(const RegisterInfo ®ister_info, 1333 Status &err) { 1334 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); 1335 iter->reset(new EntityRegister(register_info)); 1336 uint32_t ret = AddStructMember(**iter); 1337 (*iter)->SetOffset(ret); 1338 return ret; 1339} 1340 1341Materializer::Materializer() 1342 : m_dematerializer_wp(), m_current_offset(0), m_struct_alignment(8) {} 1343 1344Materializer::~Materializer() { 1345 DematerializerSP dematerializer_sp = m_dematerializer_wp.lock(); 1346 1347 if (dematerializer_sp) 1348 dematerializer_sp->Wipe(); 1349} 1350 1351Materializer::DematerializerSP 1352Materializer::Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, 1353 lldb::addr_t process_address, Status &error) { 1354 ExecutionContextScope *exe_scope = frame_sp.get(); 1355 1356 if (!exe_scope) 1357 exe_scope = map.GetBestExecutionContextScope(); 1358 1359 DematerializerSP dematerializer_sp = m_dematerializer_wp.lock(); 1360 1361 if (dematerializer_sp) { 1362 error.SetErrorToGenericError(); 1363 error.SetErrorString("Couldn't materialize: already materialized"); 1364 } 1365 1366 DematerializerSP ret( 1367 new Dematerializer(*this, frame_sp, map, process_address)); 1368 1369 if (!exe_scope) { 1370 error.SetErrorToGenericError(); 1371 error.SetErrorString("Couldn't materialize: target doesn't exist"); 1372 } 1373 1374 for (EntityUP &entity_up : m_entities) { 1375 entity_up->Materialize(frame_sp, map, process_address, error); 1376 1377 if (!error.Success()) 1378 return DematerializerSP(); 1379 } 1380 1381 if (Log *log = 1382 lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) { 1383 log->Printf( 1384 "Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64 1385 ") materialized:", 1386 static_cast<void *>(frame_sp.get()), process_address); 1387 for (EntityUP &entity_up : m_entities) 1388 entity_up->DumpToLog(map, process_address, log); 1389 } 1390 1391 m_dematerializer_wp = ret; 1392 1393 return ret; 1394} 1395 1396void Materializer::Dematerializer::Dematerialize(Status &error, 1397 lldb::addr_t frame_bottom, 1398 lldb::addr_t frame_top) { 1399 lldb::StackFrameSP frame_sp; 1400 1401 lldb::ThreadSP thread_sp = m_thread_wp.lock(); 1402 if (thread_sp) 1403 frame_sp = thread_sp->GetFrameWithStackID(m_stack_id); 1404 1405 ExecutionContextScope *exe_scope = m_map->GetBestExecutionContextScope(); 1406 1407 if (!IsValid()) { 1408 error.SetErrorToGenericError(); 1409 error.SetErrorString("Couldn't dematerialize: invalid dematerializer"); 1410 } 1411 1412 if (!exe_scope) { 1413 error.SetErrorToGenericError(); 1414 error.SetErrorString("Couldn't dematerialize: target is gone"); 1415 } else { 1416 if (Log *log = 1417 lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) { 1418 log->Printf("Materializer::Dematerialize (frame_sp = %p, process_address " 1419 "= 0x%" PRIx64 ") about to dematerialize:", 1420 static_cast<void *>(frame_sp.get()), m_process_address); 1421 for (EntityUP &entity_up : m_materializer->m_entities) 1422 entity_up->DumpToLog(*m_map, m_process_address, log); 1423 } 1424 1425 for (EntityUP &entity_up : m_materializer->m_entities) { 1426 entity_up->Dematerialize(frame_sp, *m_map, m_process_address, frame_top, 1427 frame_bottom, error); 1428 1429 if (!error.Success()) 1430 break; 1431 } 1432 } 1433 1434 Wipe(); 1435} 1436 1437void Materializer::Dematerializer::Wipe() { 1438 if (!IsValid()) 1439 return; 1440 1441 for (EntityUP &entity_up : m_materializer->m_entities) { 1442 entity_up->Wipe(*m_map, m_process_address); 1443 } 1444 1445 m_materializer = nullptr; 1446 m_map = nullptr; 1447 m_process_address = LLDB_INVALID_ADDRESS; 1448} 1449 1450Materializer::PersistentVariableDelegate::~PersistentVariableDelegate() = 1451 default; 1452