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