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