Materializer.cpp revision 309124
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 30using namespace lldb_private; 31 32uint32_t 33Materializer::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 53void 54Materializer::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 69class EntityPersistentVariable : public Materializer::Entity 70{ 71public: 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 408private: 409 lldb::ExpressionVariableSP m_persistent_variable_sp; 410 Materializer::PersistentVariableDelegate *m_delegate; 411}; 412 413uint32_t 414Materializer::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 425class EntityVariable : public Materializer::Entity 426{ 427public: 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 768private: 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 776uint32_t 777Materializer::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 786class EntityResultVariable : public Materializer::Entity 787{ 788public: 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 size_t byte_size = m_type.GetByteSize(nullptr); 822 size_t bit_align = m_type.GetTypeBitAlign(); 823 size_t byte_align = (bit_align + 7) / 8; 824 825 if (!byte_align) 826 byte_align = 1; 827 828 Error alloc_error; 829 const bool zero_memory = true; 830 831 m_temporary_allocation = map.Malloc(byte_size, 832 byte_align, 833 lldb::ePermissionsReadable | lldb::ePermissionsWritable, 834 IRMemoryMap::eAllocationPolicyMirror, 835 zero_memory, 836 alloc_error); 837 m_temporary_allocation_size = byte_size; 838 839 if (!alloc_error.Success()) 840 { 841 err.SetErrorStringWithFormat("couldn't allocate a temporary region for the result: %s", alloc_error.AsCString()); 842 return; 843 } 844 845 Error pointer_write_error; 846 847 map.WritePointerToMemory(load_addr, m_temporary_allocation, pointer_write_error); 848 849 if (!pointer_write_error.Success()) 850 { 851 err.SetErrorStringWithFormat("couldn't write the address of the temporary region for the result: %s", pointer_write_error.AsCString()); 852 } 853 } 854 } 855 856 void Dematerialize(lldb::StackFrameSP &frame_sp, 857 IRMemoryMap &map, 858 lldb::addr_t process_address, 859 lldb::addr_t frame_top, 860 lldb::addr_t frame_bottom, 861 Error &err) override 862 { 863 err.Clear(); 864 865 ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope(); 866 867 if (!exe_scope) 868 { 869 err.SetErrorString("Couldn't dematerialize a result variable: invalid execution context scope"); 870 return; 871 } 872 873 lldb::addr_t address; 874 Error read_error; 875 const lldb::addr_t load_addr = process_address + m_offset; 876 877 map.ReadPointerFromMemory (&address, load_addr, read_error); 878 879 if (!read_error.Success()) 880 { 881 err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its address"); 882 return; 883 } 884 885 lldb::TargetSP target_sp = exe_scope->CalculateTarget(); 886 887 if (!target_sp) 888 { 889 err.SetErrorString("Couldn't dematerialize a result variable: no target"); 890 return; 891 } 892 893 Error type_system_error; 894 TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage(&type_system_error, m_type.GetMinimumLanguage()); 895 896 if (!type_system) 897 { 898 err.SetErrorStringWithFormat("Couldn't dematerialize a result variable: couldn't get the corresponding type system: %s", type_system_error.AsCString()); 899 return; 900 } 901 902 PersistentExpressionState *persistent_state = type_system->GetPersistentExpressionState(); 903 904 if (!persistent_state) 905 { 906 err.SetErrorString("Couldn't dematerialize a result variable: corresponding type system doesn't handle persistent variables"); 907 return; 908 } 909 910 ConstString name = m_delegate ? m_delegate->GetName() : persistent_state->GetNextPersistentVariableName(); 911 912 lldb::ExpressionVariableSP ret = persistent_state->CreatePersistentVariable(exe_scope, 913 name, 914 m_type, 915 map.GetByteOrder(), 916 map.GetAddressByteSize()); 917 918 if (!ret) 919 { 920 err.SetErrorStringWithFormat("couldn't dematerialize a result variable: failed to make persistent variable %s", name.AsCString()); 921 return; 922 } 923 924 lldb::ProcessSP process_sp = map.GetBestExecutionContextScope()->CalculateProcess(); 925 926 if (m_delegate) 927 { 928 m_delegate->DidDematerialize(ret); 929 } 930 931 bool can_persist = (m_is_program_reference && process_sp && process_sp->CanJIT() && !(address >= frame_bottom && address < frame_top)); 932 933 if (can_persist && m_keep_in_memory) 934 { 935 ret->m_live_sp = ValueObjectConstResult::Create(exe_scope, 936 m_type, 937 name, 938 address, 939 eAddressTypeLoad, 940 map.GetAddressByteSize()); 941 } 942 943 ret->ValueUpdated(); 944 945 const size_t pvar_byte_size = ret->GetByteSize(); 946 uint8_t *pvar_data = ret->GetValueBytes(); 947 948 map.ReadMemory(pvar_data, address, pvar_byte_size, read_error); 949 950 if (!read_error.Success()) 951 { 952 err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its memory"); 953 return; 954 } 955 956 if (!can_persist || !m_keep_in_memory) 957 { 958 ret->m_flags |= ExpressionVariable::EVNeedsAllocation; 959 960 if (m_temporary_allocation != LLDB_INVALID_ADDRESS) 961 { 962 Error free_error; 963 map.Free(m_temporary_allocation, free_error); 964 } 965 } 966 else 967 { 968 ret->m_flags |= ExpressionVariable::EVIsLLDBAllocated; 969 } 970 971 m_temporary_allocation = LLDB_INVALID_ADDRESS; 972 m_temporary_allocation_size = 0; 973 } 974 975 void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override 976 { 977 StreamString dump_stream; 978 979 const lldb::addr_t load_addr = process_address + m_offset; 980 981 dump_stream.Printf("0x%" PRIx64 ": EntityResultVariable\n", load_addr); 982 983 Error err; 984 985 lldb::addr_t ptr = LLDB_INVALID_ADDRESS; 986 987 { 988 dump_stream.Printf("Pointer:\n"); 989 990 DataBufferHeap data (m_size, 0); 991 992 map.ReadMemory(data.GetBytes(), load_addr, m_size, err); 993 994 if (!err.Success()) 995 { 996 dump_stream.Printf(" <could not be read>\n"); 997 } 998 else 999 { 1000 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); 1001 1002 extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); 1003 1004 lldb::offset_t offset; 1005 1006 ptr = extractor.GetPointer(&offset); 1007 1008 dump_stream.PutChar('\n'); 1009 } 1010 } 1011 1012 if (m_temporary_allocation == LLDB_INVALID_ADDRESS) 1013 { 1014 dump_stream.Printf("Points to process memory:\n"); 1015 } 1016 else 1017 { 1018 dump_stream.Printf("Temporary allocation:\n"); 1019 } 1020 1021 if (ptr == LLDB_INVALID_ADDRESS) 1022 { 1023 dump_stream.Printf(" <could not be be found>\n"); 1024 } 1025 else 1026 { 1027 DataBufferHeap data (m_temporary_allocation_size, 0); 1028 1029 map.ReadMemory(data.GetBytes(), m_temporary_allocation, m_temporary_allocation_size, err); 1030 1031 if (!err.Success()) 1032 { 1033 dump_stream.Printf(" <could not be read>\n"); 1034 } 1035 else 1036 { 1037 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); 1038 1039 extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); 1040 1041 dump_stream.PutChar('\n'); 1042 } 1043 } 1044 1045 log->PutCString(dump_stream.GetData()); 1046 } 1047 1048 void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override 1049 { 1050 if (!m_keep_in_memory && m_temporary_allocation != LLDB_INVALID_ADDRESS) 1051 { 1052 Error free_error; 1053 1054 map.Free(m_temporary_allocation, free_error); 1055 } 1056 1057 m_temporary_allocation = LLDB_INVALID_ADDRESS; 1058 m_temporary_allocation_size = 0; 1059 } 1060 1061private: 1062 CompilerType m_type; 1063 bool m_is_program_reference; 1064 bool m_keep_in_memory; 1065 1066 lldb::addr_t m_temporary_allocation; 1067 size_t m_temporary_allocation_size; 1068 Materializer::PersistentVariableDelegate *m_delegate; 1069}; 1070 1071uint32_t 1072Materializer::AddResultVariable (const CompilerType &type, 1073 bool is_program_reference, 1074 bool keep_in_memory, 1075 PersistentVariableDelegate *delegate, 1076 Error &err) 1077{ 1078 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); 1079 iter->reset (new EntityResultVariable (type, is_program_reference, keep_in_memory, delegate)); 1080 uint32_t ret = AddStructMember(**iter); 1081 (*iter)->SetOffset(ret); 1082 return ret; 1083} 1084 1085class EntitySymbol : public Materializer::Entity 1086{ 1087public: 1088 EntitySymbol (const Symbol &symbol) : 1089 Entity(), 1090 m_symbol(symbol) 1091 { 1092 // Hard-coding to maximum size of a symbol 1093 m_size = 8; 1094 m_alignment = 8; 1095 } 1096 1097 void Materialize(lldb::StackFrameSP &frame_sp, 1098 IRMemoryMap &map, 1099 lldb::addr_t process_address, 1100 Error &err) override 1101 { 1102 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); 1103 1104 const lldb::addr_t load_addr = process_address + m_offset; 1105 1106 if (log) 1107 { 1108 log->Printf("EntitySymbol::Materialize [address = 0x%" PRIx64 ", m_symbol = %s]", 1109 (uint64_t)load_addr, 1110 m_symbol.GetName().AsCString()); 1111 } 1112 1113 const Address sym_address = m_symbol.GetAddress(); 1114 1115 ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope(); 1116 1117 lldb::TargetSP target_sp; 1118 1119 if (exe_scope) 1120 target_sp = map.GetBestExecutionContextScope()->CalculateTarget(); 1121 1122 if (!target_sp) 1123 { 1124 err.SetErrorStringWithFormat("couldn't resolve symbol %s because there is no target", m_symbol.GetName().AsCString()); 1125 return; 1126 } 1127 1128 lldb::addr_t resolved_address = sym_address.GetLoadAddress(target_sp.get()); 1129 1130 if (resolved_address == LLDB_INVALID_ADDRESS) 1131 resolved_address = sym_address.GetFileAddress(); 1132 1133 Error pointer_write_error; 1134 1135 map.WritePointerToMemory(load_addr, resolved_address, pointer_write_error); 1136 1137 if (!pointer_write_error.Success()) 1138 { 1139 err.SetErrorStringWithFormat("couldn't write the address of symbol %s: %s", m_symbol.GetName().AsCString(), pointer_write_error.AsCString()); 1140 return; 1141 } 1142 } 1143 1144 void Dematerialize(lldb::StackFrameSP &frame_sp, 1145 IRMemoryMap &map, 1146 lldb::addr_t process_address, 1147 lldb::addr_t frame_top, 1148 lldb::addr_t frame_bottom, 1149 Error &err) override 1150 { 1151 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); 1152 1153 const lldb::addr_t load_addr = process_address + m_offset; 1154 1155 if (log) 1156 { 1157 log->Printf("EntitySymbol::Dematerialize [address = 0x%" PRIx64 ", m_symbol = %s]", 1158 (uint64_t)load_addr, 1159 m_symbol.GetName().AsCString()); 1160 } 1161 1162 // no work needs to be done 1163 } 1164 1165 void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override 1166 { 1167 StreamString dump_stream; 1168 1169 Error err; 1170 1171 const lldb::addr_t load_addr = process_address + m_offset; 1172 1173 dump_stream.Printf("0x%" PRIx64 ": EntitySymbol (%s)\n", load_addr, m_symbol.GetName().AsCString()); 1174 1175 { 1176 dump_stream.Printf("Pointer:\n"); 1177 1178 DataBufferHeap data (m_size, 0); 1179 1180 map.ReadMemory(data.GetBytes(), load_addr, m_size, err); 1181 1182 if (!err.Success()) 1183 { 1184 dump_stream.Printf(" <could not be read>\n"); 1185 } 1186 else 1187 { 1188 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); 1189 1190 extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); 1191 1192 dump_stream.PutChar('\n'); 1193 } 1194 } 1195 1196 log->PutCString(dump_stream.GetData()); 1197 } 1198 1199 void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override 1200 { 1201 } 1202 1203private: 1204 Symbol m_symbol; 1205}; 1206 1207uint32_t 1208Materializer::AddSymbol (const Symbol &symbol_sp, Error &err) 1209{ 1210 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); 1211 iter->reset (new EntitySymbol (symbol_sp)); 1212 uint32_t ret = AddStructMember(**iter); 1213 (*iter)->SetOffset(ret); 1214 return ret; 1215} 1216 1217class EntityRegister : public Materializer::Entity 1218{ 1219public: 1220 EntityRegister (const RegisterInfo ®ister_info) : 1221 Entity(), 1222 m_register_info(register_info) 1223 { 1224 // Hard-coding alignment conservatively 1225 m_size = m_register_info.byte_size; 1226 m_alignment = m_register_info.byte_size; 1227 } 1228 1229 void Materialize(lldb::StackFrameSP &frame_sp, 1230 IRMemoryMap &map, 1231 lldb::addr_t process_address, 1232 Error &err) override 1233 { 1234 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); 1235 1236 const lldb::addr_t load_addr = process_address + m_offset; 1237 1238 if (log) 1239 { 1240 log->Printf("EntityRegister::Materialize [address = 0x%" PRIx64 ", m_register_info = %s]", 1241 (uint64_t)load_addr, 1242 m_register_info.name); 1243 } 1244 1245 RegisterValue reg_value; 1246 1247 if (!frame_sp.get()) 1248 { 1249 err.SetErrorStringWithFormat("couldn't materialize register %s without a stack frame", m_register_info.name); 1250 return; 1251 } 1252 1253 lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext(); 1254 1255 if (!reg_context_sp->ReadRegister(&m_register_info, reg_value)) 1256 { 1257 err.SetErrorStringWithFormat("couldn't read the value of register %s", m_register_info.name); 1258 return; 1259 } 1260 1261 DataExtractor register_data; 1262 1263 if (!reg_value.GetData(register_data)) 1264 { 1265 err.SetErrorStringWithFormat("couldn't get the data for register %s", m_register_info.name); 1266 return; 1267 } 1268 1269 if (register_data.GetByteSize() != m_register_info.byte_size) 1270 { 1271 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); 1272 return; 1273 } 1274 1275 m_register_contents.reset(new DataBufferHeap(register_data.GetDataStart(), register_data.GetByteSize())); 1276 1277 Error write_error; 1278 1279 map.WriteMemory(load_addr, register_data.GetDataStart(), register_data.GetByteSize(), write_error); 1280 1281 if (!write_error.Success()) 1282 { 1283 err.SetErrorStringWithFormat("couldn't write the contents of register %s: %s", m_register_info.name, write_error.AsCString()); 1284 return; 1285 } 1286 } 1287 1288 void Dematerialize(lldb::StackFrameSP &frame_sp, 1289 IRMemoryMap &map, 1290 lldb::addr_t process_address, 1291 lldb::addr_t frame_top, 1292 lldb::addr_t frame_bottom, 1293 Error &err) override 1294 { 1295 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); 1296 1297 const lldb::addr_t load_addr = process_address + m_offset; 1298 1299 if (log) 1300 { 1301 log->Printf("EntityRegister::Dematerialize [address = 0x%" PRIx64 ", m_register_info = %s]", 1302 (uint64_t)load_addr, 1303 m_register_info.name); 1304 } 1305 1306 Error extract_error; 1307 1308 DataExtractor register_data; 1309 1310 if (!frame_sp.get()) 1311 { 1312 err.SetErrorStringWithFormat("couldn't dematerialize register %s without a stack frame", m_register_info.name); 1313 return; 1314 } 1315 1316 lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext(); 1317 1318 map.GetMemoryData(register_data, load_addr, m_register_info.byte_size, extract_error); 1319 1320 if (!extract_error.Success()) 1321 { 1322 err.SetErrorStringWithFormat("couldn't get the data for register %s: %s", m_register_info.name, extract_error.AsCString()); 1323 return; 1324 } 1325 1326 if (!memcmp(register_data.GetDataStart(), m_register_contents->GetBytes(), register_data.GetByteSize())) 1327 { 1328 // No write required, and in particular we avoid errors if the register wasn't writable 1329 1330 m_register_contents.reset(); 1331 return; 1332 } 1333 1334 m_register_contents.reset(); 1335 1336 RegisterValue register_value (const_cast<uint8_t*>(register_data.GetDataStart()), register_data.GetByteSize(), register_data.GetByteOrder()); 1337 1338 if (!reg_context_sp->WriteRegister(&m_register_info, register_value)) 1339 { 1340 err.SetErrorStringWithFormat("couldn't write the value of register %s", m_register_info.name); 1341 return; 1342 } 1343 } 1344 1345 void DumpToLog(IRMemoryMap &map, lldb::addr_t process_address, Log *log) override 1346 { 1347 StreamString dump_stream; 1348 1349 Error err; 1350 1351 const lldb::addr_t load_addr = process_address + m_offset; 1352 1353 1354 dump_stream.Printf("0x%" PRIx64 ": EntityRegister (%s)\n", load_addr, m_register_info.name); 1355 1356 { 1357 dump_stream.Printf("Value:\n"); 1358 1359 DataBufferHeap data (m_size, 0); 1360 1361 map.ReadMemory(data.GetBytes(), load_addr, m_size, err); 1362 1363 if (!err.Success()) 1364 { 1365 dump_stream.Printf(" <could not be read>\n"); 1366 } 1367 else 1368 { 1369 DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); 1370 1371 extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); 1372 1373 dump_stream.PutChar('\n'); 1374 } 1375 } 1376 1377 log->PutCString(dump_stream.GetData()); 1378 } 1379 1380 void Wipe(IRMemoryMap &map, lldb::addr_t process_address) override 1381 { 1382 } 1383 1384private: 1385 RegisterInfo m_register_info; 1386 lldb::DataBufferSP m_register_contents; 1387}; 1388 1389uint32_t 1390Materializer::AddRegister (const RegisterInfo ®ister_info, Error &err) 1391{ 1392 EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); 1393 iter->reset (new EntityRegister (register_info)); 1394 uint32_t ret = AddStructMember(**iter); 1395 (*iter)->SetOffset(ret); 1396 return ret; 1397} 1398 1399Materializer::Materializer () : 1400 m_dematerializer_wp(), 1401 m_current_offset(0), 1402 m_struct_alignment(8) 1403{ 1404} 1405 1406Materializer::~Materializer () 1407{ 1408 DematerializerSP dematerializer_sp = m_dematerializer_wp.lock(); 1409 1410 if (dematerializer_sp) 1411 dematerializer_sp->Wipe(); 1412} 1413 1414Materializer::DematerializerSP 1415Materializer::Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &error) 1416{ 1417 ExecutionContextScope *exe_scope = frame_sp.get(); 1418 1419 if (!exe_scope) 1420 exe_scope = map.GetBestExecutionContextScope(); 1421 1422 DematerializerSP dematerializer_sp = m_dematerializer_wp.lock(); 1423 1424 if (dematerializer_sp) 1425 { 1426 error.SetErrorToGenericError(); 1427 error.SetErrorString("Couldn't materialize: already materialized"); 1428 } 1429 1430 DematerializerSP ret(new Dematerializer(*this, frame_sp, map, process_address)); 1431 1432 if (!exe_scope) 1433 { 1434 error.SetErrorToGenericError(); 1435 error.SetErrorString("Couldn't materialize: target doesn't exist"); 1436 } 1437 1438 for (EntityUP &entity_up : m_entities) 1439 { 1440 entity_up->Materialize(frame_sp, map, process_address, error); 1441 1442 if (!error.Success()) 1443 return DematerializerSP(); 1444 } 1445 1446 if (Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) 1447 { 1448 log->Printf("Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64 ") materialized:", 1449 static_cast<void*>(frame_sp.get()), process_address); 1450 for (EntityUP &entity_up : m_entities) 1451 entity_up->DumpToLog(map, process_address, log); 1452 } 1453 1454 m_dematerializer_wp = ret; 1455 1456 return ret; 1457} 1458 1459void 1460Materializer::Dematerializer::Dematerialize (Error &error, 1461 lldb::addr_t frame_bottom, 1462 lldb::addr_t frame_top) 1463{ 1464 lldb::StackFrameSP frame_sp; 1465 1466 lldb::ThreadSP thread_sp = m_thread_wp.lock(); 1467 if (thread_sp) 1468 frame_sp = thread_sp->GetFrameWithStackID(m_stack_id); 1469 1470 ExecutionContextScope *exe_scope = m_map->GetBestExecutionContextScope(); 1471 1472 if (!IsValid()) 1473 { 1474 error.SetErrorToGenericError(); 1475 error.SetErrorString("Couldn't dematerialize: invalid dematerializer"); 1476 } 1477 1478 if (!exe_scope) 1479 { 1480 error.SetErrorToGenericError(); 1481 error.SetErrorString("Couldn't dematerialize: target is gone"); 1482 } 1483 else 1484 { 1485 if (Log *log =lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) 1486 { 1487 log->Printf("Materializer::Dematerialize (frame_sp = %p, process_address = 0x%" PRIx64 ") about to dematerialize:", 1488 static_cast<void*>(frame_sp.get()), m_process_address); 1489 for (EntityUP &entity_up : m_materializer->m_entities) 1490 entity_up->DumpToLog(*m_map, m_process_address, log); 1491 } 1492 1493 for (EntityUP &entity_up : m_materializer->m_entities) 1494 { 1495 entity_up->Dematerialize (frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error); 1496 1497 if (!error.Success()) 1498 break; 1499 } 1500 } 1501 1502 Wipe(); 1503} 1504 1505void 1506Materializer::Dematerializer::Wipe () 1507{ 1508 if (!IsValid()) 1509 return; 1510 1511 for (EntityUP &entity_up : m_materializer->m_entities) 1512 { 1513 entity_up->Wipe (*m_map, m_process_address); 1514 } 1515 1516 m_materializer = nullptr; 1517 m_map = nullptr; 1518 m_process_address = LLDB_INVALID_ADDRESS; 1519} 1520 1521Materializer::PersistentVariableDelegate::~PersistentVariableDelegate() = default; 1522