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