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