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