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