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