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