Materializer.cpp revision 254721
1254721Semaste//===-- Materializer.cpp ----------------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include "lldb/Core/Log.h" 11254721Semaste#include "lldb/Core/RegisterValue.h" 12254721Semaste#include "lldb/Core/ValueObjectConstResult.h" 13254721Semaste#include "lldb/Core/ValueObjectVariable.h" 14254721Semaste#include "lldb/Expression/ClangExpressionVariable.h" 15254721Semaste#include "lldb/Expression/Materializer.h" 16254721Semaste#include "lldb/Symbol/ClangASTContext.h" 17254721Semaste#include "lldb/Symbol/Symbol.h" 18254721Semaste#include "lldb/Symbol/Type.h" 19254721Semaste#include "lldb/Symbol/Variable.h" 20254721Semaste#include "lldb/Target/ExecutionContext.h" 21254721Semaste#include "lldb/Target/RegisterContext.h" 22254721Semaste#include "lldb/Target/StackFrame.h" 23254721Semaste#include "lldb/Target/Target.h" 24254721Semaste#include "lldb/Target/Thread.h" 25254721Semaste 26254721Semasteusing namespace lldb_private; 27254721Semaste 28254721Semasteuint32_t 29254721SemasteMaterializer::AddStructMember (Entity &entity) 30254721Semaste{ 31254721Semaste uint32_t size = entity.GetSize(); 32254721Semaste uint32_t alignment = entity.GetAlignment(); 33254721Semaste 34254721Semaste uint32_t ret; 35254721Semaste 36254721Semaste if (m_current_offset == 0) 37254721Semaste m_struct_alignment = alignment; 38254721Semaste 39254721Semaste if (m_current_offset % alignment) 40254721Semaste m_current_offset += (alignment - (m_current_offset % alignment)); 41254721Semaste 42254721Semaste ret = m_current_offset; 43254721Semaste 44254721Semaste m_current_offset += size; 45254721Semaste 46254721Semaste return ret; 47254721Semaste} 48254721Semaste 49254721Semastevoid 50254721SemasteMaterializer::Entity::SetSizeAndAlignmentFromType (ClangASTType &type) 51254721Semaste{ 52254721Semaste m_size = type.GetByteSize(); 53254721Semaste 54254721Semaste uint32_t bit_alignment = type.GetTypeBitAlign(); 55254721Semaste 56254721Semaste if (bit_alignment % 8) 57254721Semaste { 58254721Semaste bit_alignment += 8; 59254721Semaste bit_alignment &= ~((uint32_t)0x111u); 60254721Semaste } 61254721Semaste 62254721Semaste m_alignment = bit_alignment / 8; 63254721Semaste} 64254721Semaste 65254721Semasteclass EntityPersistentVariable : public Materializer::Entity 66254721Semaste{ 67254721Semastepublic: 68254721Semaste EntityPersistentVariable (lldb::ClangExpressionVariableSP &persistent_variable_sp) : 69254721Semaste Entity(), 70254721Semaste m_persistent_variable_sp(persistent_variable_sp) 71254721Semaste { 72254721Semaste // Hard-coding to maximum size of a pointer since persistent variables are materialized by reference 73254721Semaste m_size = 8; 74254721Semaste m_alignment = 8; 75254721Semaste } 76254721Semaste 77254721Semaste void MakeAllocation (IRMemoryMap &map, Error &err) 78254721Semaste { 79254721Semaste Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); 80254721Semaste 81254721Semaste // Allocate a spare memory area to store the persistent variable's contents. 82254721Semaste 83254721Semaste Error allocate_error; 84254721Semaste 85254721Semaste lldb::addr_t mem = map.Malloc(m_persistent_variable_sp->GetByteSize(), 86254721Semaste 8, 87254721Semaste lldb::ePermissionsReadable | lldb::ePermissionsWritable, 88254721Semaste IRMemoryMap::eAllocationPolicyMirror, 89254721Semaste allocate_error); 90254721Semaste 91254721Semaste if (!allocate_error.Success()) 92254721Semaste { 93254721Semaste err.SetErrorStringWithFormat("couldn't allocate a memory area to store %s: %s", m_persistent_variable_sp->GetName().GetCString(), allocate_error.AsCString()); 94254721Semaste return; 95254721Semaste } 96254721Semaste 97254721Semaste if (log) 98254721Semaste log->Printf("Allocated %s (0x%" PRIx64 ") sucessfully", m_persistent_variable_sp->GetName().GetCString(), mem); 99254721Semaste 100254721Semaste // Put the location of the spare memory into the live data of the ValueObject. 101254721Semaste 102254721Semaste m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create (map.GetBestExecutionContextScope(), 103254721Semaste m_persistent_variable_sp->GetTypeFromUser(), 104254721Semaste m_persistent_variable_sp->GetName(), 105254721Semaste mem, 106254721Semaste eAddressTypeLoad, 107254721Semaste m_persistent_variable_sp->GetByteSize()); 108254721Semaste 109254721Semaste // Clear the flag if the variable will never be deallocated. 110254721Semaste 111254721Semaste if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVKeepInTarget) 112254721Semaste { 113254721Semaste Error leak_error; 114254721Semaste map.Leak(mem, leak_error); 115254721Semaste m_persistent_variable_sp->m_flags &= ~ClangExpressionVariable::EVNeedsAllocation; 116254721Semaste } 117254721Semaste 118254721Semaste // Write the contents of the variable to the area. 119254721Semaste 120254721Semaste Error write_error; 121254721Semaste 122254721Semaste map.WriteMemory (mem, 123254721Semaste m_persistent_variable_sp->GetValueBytes(), 124254721Semaste m_persistent_variable_sp->GetByteSize(), 125254721Semaste write_error); 126254721Semaste 127254721Semaste if (!write_error.Success()) 128254721Semaste { 129254721Semaste err.SetErrorStringWithFormat ("couldn't write %s to the target: %s", m_persistent_variable_sp->GetName().AsCString(), 130254721Semaste write_error.AsCString()); 131254721Semaste return; 132254721Semaste } 133254721Semaste } 134254721Semaste 135254721Semaste void DestroyAllocation (IRMemoryMap &map, Error &err) 136254721Semaste { 137254721Semaste Error deallocate_error; 138254721Semaste 139254721Semaste map.Free((lldb::addr_t)m_persistent_variable_sp->m_live_sp->GetValue().GetScalar().ULongLong(), deallocate_error); 140254721Semaste 141254721Semaste m_persistent_variable_sp->m_live_sp.reset(); 142254721Semaste 143254721Semaste if (!deallocate_error.Success()) 144254721Semaste { 145254721Semaste err.SetErrorStringWithFormat ("couldn't deallocate memory for %s: %s", m_persistent_variable_sp->GetName().GetCString(), deallocate_error.AsCString()); 146254721Semaste } 147254721Semaste } 148254721Semaste 149254721Semaste void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err) 150254721Semaste { 151254721Semaste Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); 152254721Semaste 153254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 154254721Semaste 155254721Semaste if (log) 156254721Semaste { 157254721Semaste log->Printf("EntityPersistentVariable::Materialize [address = 0x%" PRIx64 ", m_name = %s, m_flags = 0x%hx]", 158254721Semaste (uint64_t)load_addr, 159254721Semaste m_persistent_variable_sp->GetName().AsCString(), 160254721Semaste m_persistent_variable_sp->m_flags); 161254721Semaste } 162254721Semaste 163254721Semaste if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVNeedsAllocation) 164254721Semaste { 165254721Semaste MakeAllocation(map, err); 166254721Semaste m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated; 167254721Semaste 168254721Semaste if (!err.Success()) 169254721Semaste return; 170254721Semaste } 171254721Semaste 172254721Semaste if ((m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsProgramReference && m_persistent_variable_sp->m_live_sp) || 173254721Semaste m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsLLDBAllocated) 174254721Semaste { 175254721Semaste Error write_error; 176254721Semaste 177254721Semaste map.WriteScalarToMemory(load_addr, 178254721Semaste m_persistent_variable_sp->m_live_sp->GetValue().GetScalar(), 179254721Semaste map.GetAddressByteSize(), 180254721Semaste write_error); 181254721Semaste 182254721Semaste if (!write_error.Success()) 183254721Semaste { 184254721Semaste err.SetErrorStringWithFormat("couldn't write the location of %s to memory: %s", m_persistent_variable_sp->GetName().AsCString(), write_error.AsCString()); 185254721Semaste } 186254721Semaste } 187254721Semaste else 188254721Semaste { 189254721Semaste err.SetErrorStringWithFormat("no materialization happened for persistent variable %s", m_persistent_variable_sp->GetName().AsCString()); 190254721Semaste return; 191254721Semaste } 192254721Semaste } 193254721Semaste 194254721Semaste void Dematerialize (lldb::StackFrameSP &frame_sp, 195254721Semaste IRMemoryMap &map, 196254721Semaste lldb::addr_t process_address, 197254721Semaste lldb::addr_t frame_top, 198254721Semaste lldb::addr_t frame_bottom, 199254721Semaste Error &err) 200254721Semaste { 201254721Semaste Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); 202254721Semaste 203254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 204254721Semaste 205254721Semaste if (log) 206254721Semaste { 207254721Semaste log->Printf("EntityPersistentVariable::Dematerialize [address = 0x%" PRIx64 ", m_name = %s, m_flags = 0x%hx]", 208254721Semaste (uint64_t)process_address + m_offset, 209254721Semaste m_persistent_variable_sp->GetName().AsCString(), 210254721Semaste m_persistent_variable_sp->m_flags); 211254721Semaste } 212254721Semaste 213254721Semaste if ((m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsLLDBAllocated) || 214254721Semaste (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsProgramReference)) 215254721Semaste { 216254721Semaste if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsProgramReference && 217254721Semaste !m_persistent_variable_sp->m_live_sp) 218254721Semaste { 219254721Semaste // If the reference comes from the program, then the ClangExpressionVariable's 220254721Semaste // live variable data hasn't been set up yet. Do this now. 221254721Semaste 222254721Semaste lldb::addr_t location; 223254721Semaste Error read_error; 224254721Semaste 225254721Semaste map.ReadPointerFromMemory(&location, load_addr, read_error); 226254721Semaste 227254721Semaste if (!read_error.Success()) 228254721Semaste { 229254721Semaste err.SetErrorStringWithFormat("couldn't read the address of program-allocated variable %s: %s", m_persistent_variable_sp->GetName().GetCString(), read_error.AsCString()); 230254721Semaste return; 231254721Semaste } 232254721Semaste 233254721Semaste m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create (map.GetBestExecutionContextScope (), 234254721Semaste m_persistent_variable_sp->GetTypeFromUser(), 235254721Semaste m_persistent_variable_sp->GetName(), 236254721Semaste location, 237254721Semaste eAddressTypeLoad, 238254721Semaste m_persistent_variable_sp->GetByteSize()); 239254721Semaste 240254721Semaste if (frame_top != LLDB_INVALID_ADDRESS && 241254721Semaste frame_bottom != LLDB_INVALID_ADDRESS && 242254721Semaste location >= frame_bottom && 243254721Semaste location <= frame_top) 244254721Semaste { 245254721Semaste // If the variable is resident in the stack frame created by the expression, 246254721Semaste // then it cannot be relied upon to stay around. We treat it as needing 247254721Semaste // reallocation. 248254721Semaste m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated; 249254721Semaste m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation; 250254721Semaste m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVNeedsFreezeDry; 251254721Semaste m_persistent_variable_sp->m_flags &= ~ClangExpressionVariable::EVIsProgramReference; 252254721Semaste } 253254721Semaste } 254254721Semaste 255254721Semaste lldb::addr_t mem = m_persistent_variable_sp->m_live_sp->GetValue().GetScalar().ULongLong(); 256254721Semaste 257254721Semaste if (!m_persistent_variable_sp->m_live_sp) 258254721Semaste { 259254721Semaste err.SetErrorStringWithFormat("couldn't find the memory area used to store %s", m_persistent_variable_sp->GetName().GetCString()); 260254721Semaste return; 261254721Semaste } 262254721Semaste 263254721Semaste if (m_persistent_variable_sp->m_live_sp->GetValue().GetValueAddressType() != eAddressTypeLoad) 264254721Semaste { 265254721Semaste err.SetErrorStringWithFormat("the address of the memory area for %s is in an incorrect format", m_persistent_variable_sp->GetName().GetCString()); 266254721Semaste return; 267254721Semaste } 268254721Semaste 269254721Semaste if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVNeedsFreezeDry || 270254721Semaste m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVKeepInTarget) 271254721Semaste { 272254721Semaste if (log) 273254721Semaste 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()); 274254721Semaste 275254721Semaste // Read the contents of the spare memory area 276254721Semaste 277254721Semaste m_persistent_variable_sp->ValueUpdated (); 278254721Semaste 279254721Semaste Error read_error; 280254721Semaste 281254721Semaste map.ReadMemory(m_persistent_variable_sp->GetValueBytes(), 282254721Semaste mem, 283254721Semaste m_persistent_variable_sp->GetByteSize(), 284254721Semaste read_error); 285254721Semaste 286254721Semaste if (!read_error.Success()) 287254721Semaste { 288254721Semaste err.SetErrorStringWithFormat ("couldn't read the contents of %s from memory: %s", m_persistent_variable_sp->GetName().GetCString(), read_error.AsCString()); 289254721Semaste return; 290254721Semaste } 291254721Semaste 292254721Semaste m_persistent_variable_sp->m_flags &= ~ClangExpressionVariable::EVNeedsFreezeDry; 293254721Semaste } 294254721Semaste } 295254721Semaste else 296254721Semaste { 297254721Semaste err.SetErrorStringWithFormat("no dematerialization happened for persistent variable %s", m_persistent_variable_sp->GetName().AsCString()); 298254721Semaste return; 299254721Semaste } 300254721Semaste 301254721Semaste lldb::ProcessSP process_sp = map.GetBestExecutionContextScope()->CalculateProcess(); 302254721Semaste if (!process_sp || 303254721Semaste !process_sp->CanJIT()) 304254721Semaste { 305254721Semaste // Allocations are not persistent so persistent variables cannot stay materialized. 306254721Semaste 307254721Semaste m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation; 308254721Semaste 309254721Semaste DestroyAllocation(map, err); 310254721Semaste if (!err.Success()) 311254721Semaste return; 312254721Semaste } 313254721Semaste else if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVNeedsAllocation && 314254721Semaste !(m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVKeepInTarget)) 315254721Semaste { 316254721Semaste DestroyAllocation(map, err); 317254721Semaste if (!err.Success()) 318254721Semaste return; 319254721Semaste } 320254721Semaste } 321254721Semaste 322254721Semaste void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log) 323254721Semaste { 324254721Semaste StreamString dump_stream; 325254721Semaste 326254721Semaste Error err; 327254721Semaste 328254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 329254721Semaste 330254721Semaste dump_stream.Printf("0x%" PRIx64 ": EntityPersistentVariable (%s)\n", load_addr, m_persistent_variable_sp->GetName().AsCString()); 331254721Semaste 332254721Semaste { 333254721Semaste dump_stream.Printf("Pointer:\n"); 334254721Semaste 335254721Semaste DataBufferHeap data (m_size, 0); 336254721Semaste 337254721Semaste map.ReadMemory(data.GetBytes(), load_addr, m_size, err); 338254721Semaste 339254721Semaste if (!err.Success()) 340254721Semaste { 341254721Semaste dump_stream.Printf(" <could not be read>\n"); 342254721Semaste } 343254721Semaste else 344254721Semaste { 345254721Semaste DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); 346254721Semaste 347254721Semaste extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); 348254721Semaste 349254721Semaste dump_stream.PutChar('\n'); 350254721Semaste } 351254721Semaste } 352254721Semaste 353254721Semaste { 354254721Semaste dump_stream.Printf("Target:\n"); 355254721Semaste 356254721Semaste lldb::addr_t target_address; 357254721Semaste 358254721Semaste map.ReadPointerFromMemory (&target_address, load_addr, err); 359254721Semaste 360254721Semaste if (!err.Success()) 361254721Semaste { 362254721Semaste dump_stream.Printf(" <could not be read>\n"); 363254721Semaste } 364254721Semaste else 365254721Semaste { 366254721Semaste DataBufferHeap data (m_persistent_variable_sp->GetByteSize(), 0); 367254721Semaste 368254721Semaste map.ReadMemory(data.GetBytes(), target_address, m_persistent_variable_sp->GetByteSize(), err); 369254721Semaste 370254721Semaste if (!err.Success()) 371254721Semaste { 372254721Semaste dump_stream.Printf(" <could not be read>\n"); 373254721Semaste } 374254721Semaste else 375254721Semaste { 376254721Semaste DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); 377254721Semaste 378254721Semaste extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, target_address); 379254721Semaste 380254721Semaste dump_stream.PutChar('\n'); 381254721Semaste } 382254721Semaste } 383254721Semaste } 384254721Semaste 385254721Semaste log->PutCString(dump_stream.GetData()); 386254721Semaste } 387254721Semaste 388254721Semaste void Wipe (IRMemoryMap &map, lldb::addr_t process_address) 389254721Semaste { 390254721Semaste } 391254721Semasteprivate: 392254721Semaste lldb::ClangExpressionVariableSP m_persistent_variable_sp; 393254721Semaste}; 394254721Semaste 395254721Semasteuint32_t 396254721SemasteMaterializer::AddPersistentVariable (lldb::ClangExpressionVariableSP &persistent_variable_sp, Error &err) 397254721Semaste{ 398254721Semaste EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); 399254721Semaste iter->reset (new EntityPersistentVariable (persistent_variable_sp)); 400254721Semaste uint32_t ret = AddStructMember(**iter); 401254721Semaste (*iter)->SetOffset(ret); 402254721Semaste return ret; 403254721Semaste} 404254721Semaste 405254721Semasteclass EntityVariable : public Materializer::Entity 406254721Semaste{ 407254721Semastepublic: 408254721Semaste EntityVariable (lldb::VariableSP &variable_sp) : 409254721Semaste Entity(), 410254721Semaste m_variable_sp(variable_sp), 411254721Semaste m_is_reference(false), 412254721Semaste m_temporary_allocation(LLDB_INVALID_ADDRESS), 413254721Semaste m_temporary_allocation_size(0) 414254721Semaste { 415254721Semaste // Hard-coding to maximum size of a pointer since all variables are materialized by reference 416254721Semaste m_size = 8; 417254721Semaste m_alignment = 8; 418254721Semaste m_is_reference = m_variable_sp->GetType()->GetClangForwardType().IsReferenceType(); 419254721Semaste } 420254721Semaste 421254721Semaste void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err) 422254721Semaste { 423254721Semaste Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); 424254721Semaste 425254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 426254721Semaste if (log) 427254721Semaste { 428254721Semaste log->Printf("EntityVariable::Materialize [address = 0x%" PRIx64 ", m_variable_sp = %s]", 429254721Semaste (uint64_t)load_addr, 430254721Semaste m_variable_sp->GetName().AsCString()); 431254721Semaste } 432254721Semaste 433254721Semaste ExecutionContextScope *scope = frame_sp.get(); 434254721Semaste 435254721Semaste if (!scope) 436254721Semaste scope = map.GetBestExecutionContextScope(); 437254721Semaste 438254721Semaste lldb::ValueObjectSP valobj_sp = ValueObjectVariable::Create(scope, m_variable_sp); 439254721Semaste 440254721Semaste if (!valobj_sp) 441254721Semaste { 442254721Semaste err.SetErrorStringWithFormat("couldn't get a value object for variable %s", m_variable_sp->GetName().AsCString()); 443254721Semaste return; 444254721Semaste } 445254721Semaste 446254721Semaste if (m_is_reference) 447254721Semaste { 448254721Semaste DataExtractor valobj_extractor; 449254721Semaste valobj_sp->GetData(valobj_extractor); 450254721Semaste lldb::offset_t offset = 0; 451254721Semaste lldb::addr_t reference_addr = valobj_extractor.GetAddress(&offset); 452254721Semaste 453254721Semaste Error write_error; 454254721Semaste map.WritePointerToMemory(load_addr, reference_addr, write_error); 455254721Semaste 456254721Semaste if (!write_error.Success()) 457254721Semaste { 458254721Semaste err.SetErrorStringWithFormat("couldn't write the contents of reference variable %s to memory: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString()); 459254721Semaste return; 460254721Semaste } 461254721Semaste } 462254721Semaste else 463254721Semaste { 464254721Semaste Error get_address_error; 465254721Semaste lldb::ValueObjectSP addr_of_valobj_sp = valobj_sp->AddressOf(get_address_error); 466254721Semaste if (get_address_error.Success()) 467254721Semaste { 468254721Semaste DataExtractor valobj_extractor; 469254721Semaste addr_of_valobj_sp->GetData(valobj_extractor); 470254721Semaste lldb::offset_t offset = 0; 471254721Semaste lldb::addr_t addr_of_valobj_addr = valobj_extractor.GetAddress(&offset); 472254721Semaste 473254721Semaste Error write_error; 474254721Semaste map.WritePointerToMemory(load_addr, addr_of_valobj_addr, write_error); 475254721Semaste 476254721Semaste if (!write_error.Success()) 477254721Semaste { 478254721Semaste err.SetErrorStringWithFormat("couldn't write the address of variable %s to memory: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString()); 479254721Semaste return; 480254721Semaste } 481254721Semaste } 482254721Semaste else 483254721Semaste { 484254721Semaste DataExtractor data; 485254721Semaste valobj_sp->GetData(data); 486254721Semaste 487254721Semaste if (m_temporary_allocation != LLDB_INVALID_ADDRESS) 488254721Semaste { 489254721Semaste err.SetErrorStringWithFormat("trying to create a temporary region for %s but one exists", m_variable_sp->GetName().AsCString()); 490254721Semaste return; 491254721Semaste } 492254721Semaste 493254721Semaste if (data.GetByteSize() != m_variable_sp->GetType()->GetByteSize()) 494254721Semaste { 495254721Semaste if (data.GetByteSize() == 0 && m_variable_sp->LocationExpression().IsValid() == false) 496254721Semaste { 497254721Semaste err.SetErrorStringWithFormat("the variable '%s' has no location, it may have been optimized out", m_variable_sp->GetName().AsCString()); 498254721Semaste } 499254721Semaste else 500254721Semaste { 501254721Semaste err.SetErrorStringWithFormat("size of variable %s disagrees with the ValueObject's size", m_variable_sp->GetName().AsCString()); 502254721Semaste } 503254721Semaste return; 504254721Semaste } 505254721Semaste 506254721Semaste size_t bit_align = m_variable_sp->GetType()->GetClangLayoutType().GetTypeBitAlign(); 507254721Semaste size_t byte_align = (bit_align + 7) / 8; 508254721Semaste 509254721Semaste Error alloc_error; 510254721Semaste 511254721Semaste m_temporary_allocation = map.Malloc(data.GetByteSize(), byte_align, lldb::ePermissionsReadable | lldb::ePermissionsWritable, IRMemoryMap::eAllocationPolicyMirror, alloc_error); 512254721Semaste m_temporary_allocation_size = data.GetByteSize(); 513254721Semaste 514254721Semaste if (!alloc_error.Success()) 515254721Semaste { 516254721Semaste err.SetErrorStringWithFormat("couldn't allocate a temporary region for %s: %s", m_variable_sp->GetName().AsCString(), alloc_error.AsCString()); 517254721Semaste return; 518254721Semaste } 519254721Semaste 520254721Semaste Error write_error; 521254721Semaste 522254721Semaste map.WriteMemory(m_temporary_allocation, data.GetDataStart(), data.GetByteSize(), write_error); 523254721Semaste 524254721Semaste if (!write_error.Success()) 525254721Semaste { 526254721Semaste err.SetErrorStringWithFormat("couldn't write to the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString()); 527254721Semaste return; 528254721Semaste } 529254721Semaste 530254721Semaste Error pointer_write_error; 531254721Semaste 532254721Semaste map.WritePointerToMemory(load_addr, m_temporary_allocation, pointer_write_error); 533254721Semaste 534254721Semaste if (!pointer_write_error.Success()) 535254721Semaste { 536254721Semaste err.SetErrorStringWithFormat("couldn't write the address of the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), pointer_write_error.AsCString()); 537254721Semaste } 538254721Semaste } 539254721Semaste } 540254721Semaste } 541254721Semaste 542254721Semaste void Dematerialize (lldb::StackFrameSP &frame_sp, 543254721Semaste IRMemoryMap &map, 544254721Semaste lldb::addr_t process_address, 545254721Semaste lldb::addr_t frame_top, 546254721Semaste lldb::addr_t frame_bottom, 547254721Semaste Error &err) 548254721Semaste { 549254721Semaste Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); 550254721Semaste 551254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 552254721Semaste if (log) 553254721Semaste { 554254721Semaste log->Printf("EntityVariable::Dematerialize [address = 0x%" PRIx64 ", m_variable_sp = %s]", 555254721Semaste (uint64_t)load_addr, 556254721Semaste m_variable_sp->GetName().AsCString()); 557254721Semaste } 558254721Semaste 559254721Semaste if (m_temporary_allocation != LLDB_INVALID_ADDRESS) 560254721Semaste { 561254721Semaste ExecutionContextScope *scope = frame_sp.get(); 562254721Semaste 563254721Semaste if (!scope) 564254721Semaste scope = map.GetBestExecutionContextScope(); 565254721Semaste 566254721Semaste lldb::ValueObjectSP valobj_sp = ValueObjectVariable::Create(scope, m_variable_sp); 567254721Semaste 568254721Semaste if (!valobj_sp) 569254721Semaste { 570254721Semaste err.SetErrorStringWithFormat("couldn't get a value object for variable %s", m_variable_sp->GetName().AsCString()); 571254721Semaste return; 572254721Semaste } 573254721Semaste 574254721Semaste lldb_private::DataExtractor data; 575254721Semaste 576254721Semaste Error extract_error; 577254721Semaste 578254721Semaste map.GetMemoryData(data, m_temporary_allocation, valobj_sp->GetByteSize(), extract_error); 579254721Semaste 580254721Semaste if (!extract_error.Success()) 581254721Semaste { 582254721Semaste err.SetErrorStringWithFormat("couldn't get the data for variable %s", m_variable_sp->GetName().AsCString()); 583254721Semaste return; 584254721Semaste } 585254721Semaste 586254721Semaste Error set_error; 587254721Semaste 588254721Semaste valobj_sp->SetData(data, set_error); 589254721Semaste 590254721Semaste if (!set_error.Success()) 591254721Semaste { 592254721Semaste err.SetErrorStringWithFormat("couldn't write the new contents of %s back into the variable", m_variable_sp->GetName().AsCString()); 593254721Semaste return; 594254721Semaste } 595254721Semaste 596254721Semaste Error free_error; 597254721Semaste 598254721Semaste map.Free(m_temporary_allocation, free_error); 599254721Semaste 600254721Semaste if (!free_error.Success()) 601254721Semaste { 602254721Semaste err.SetErrorStringWithFormat("couldn't free the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), free_error.AsCString()); 603254721Semaste return; 604254721Semaste } 605254721Semaste 606254721Semaste m_temporary_allocation = LLDB_INVALID_ADDRESS; 607254721Semaste m_temporary_allocation_size = 0; 608254721Semaste } 609254721Semaste } 610254721Semaste 611254721Semaste void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log) 612254721Semaste { 613254721Semaste StreamString dump_stream; 614254721Semaste 615254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 616254721Semaste dump_stream.Printf("0x%" PRIx64 ": EntityVariable\n", load_addr); 617254721Semaste 618254721Semaste Error err; 619254721Semaste 620254721Semaste lldb::addr_t ptr = LLDB_INVALID_ADDRESS; 621254721Semaste 622254721Semaste { 623254721Semaste dump_stream.Printf("Pointer:\n"); 624254721Semaste 625254721Semaste DataBufferHeap data (m_size, 0); 626254721Semaste 627254721Semaste map.ReadMemory(data.GetBytes(), load_addr, m_size, err); 628254721Semaste 629254721Semaste if (!err.Success()) 630254721Semaste { 631254721Semaste dump_stream.Printf(" <could not be read>\n"); 632254721Semaste } 633254721Semaste else 634254721Semaste { 635254721Semaste DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); 636254721Semaste 637254721Semaste extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); 638254721Semaste 639254721Semaste lldb::offset_t offset; 640254721Semaste 641254721Semaste ptr = extractor.GetPointer(&offset); 642254721Semaste 643254721Semaste dump_stream.PutChar('\n'); 644254721Semaste } 645254721Semaste } 646254721Semaste 647254721Semaste if (m_temporary_allocation == LLDB_INVALID_ADDRESS) 648254721Semaste { 649254721Semaste dump_stream.Printf("Points to process memory:\n"); 650254721Semaste } 651254721Semaste else 652254721Semaste { 653254721Semaste dump_stream.Printf("Temporary allocation:\n"); 654254721Semaste } 655254721Semaste 656254721Semaste if (ptr == LLDB_INVALID_ADDRESS) 657254721Semaste { 658254721Semaste dump_stream.Printf(" <could not be be found>\n"); 659254721Semaste } 660254721Semaste else 661254721Semaste { 662254721Semaste DataBufferHeap data (m_temporary_allocation_size, 0); 663254721Semaste 664254721Semaste map.ReadMemory(data.GetBytes(), m_temporary_allocation, m_temporary_allocation_size, err); 665254721Semaste 666254721Semaste if (!err.Success()) 667254721Semaste { 668254721Semaste dump_stream.Printf(" <could not be read>\n"); 669254721Semaste } 670254721Semaste else 671254721Semaste { 672254721Semaste DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); 673254721Semaste 674254721Semaste extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); 675254721Semaste 676254721Semaste dump_stream.PutChar('\n'); 677254721Semaste } 678254721Semaste } 679254721Semaste 680254721Semaste log->PutCString(dump_stream.GetData()); 681254721Semaste } 682254721Semaste 683254721Semaste void Wipe (IRMemoryMap &map, lldb::addr_t process_address) 684254721Semaste { 685254721Semaste if (m_temporary_allocation != LLDB_INVALID_ADDRESS) 686254721Semaste { 687254721Semaste Error free_error; 688254721Semaste 689254721Semaste map.Free(m_temporary_allocation, free_error); 690254721Semaste 691254721Semaste m_temporary_allocation = LLDB_INVALID_ADDRESS; 692254721Semaste m_temporary_allocation_size = 0; 693254721Semaste } 694254721Semaste 695254721Semaste } 696254721Semasteprivate: 697254721Semaste lldb::VariableSP m_variable_sp; 698254721Semaste bool m_is_reference; 699254721Semaste lldb::addr_t m_temporary_allocation; 700254721Semaste size_t m_temporary_allocation_size; 701254721Semaste}; 702254721Semaste 703254721Semasteuint32_t 704254721SemasteMaterializer::AddVariable (lldb::VariableSP &variable_sp, Error &err) 705254721Semaste{ 706254721Semaste EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); 707254721Semaste iter->reset (new EntityVariable (variable_sp)); 708254721Semaste uint32_t ret = AddStructMember(**iter); 709254721Semaste (*iter)->SetOffset(ret); 710254721Semaste return ret; 711254721Semaste} 712254721Semaste 713254721Semasteclass EntityResultVariable : public Materializer::Entity 714254721Semaste{ 715254721Semastepublic: 716254721Semaste EntityResultVariable (const TypeFromUser &type, bool is_program_reference, bool keep_in_memory) : 717254721Semaste Entity(), 718254721Semaste m_type(type), 719254721Semaste m_is_program_reference(is_program_reference), 720254721Semaste m_keep_in_memory(keep_in_memory), 721254721Semaste m_temporary_allocation(LLDB_INVALID_ADDRESS), 722254721Semaste m_temporary_allocation_size(0) 723254721Semaste { 724254721Semaste // Hard-coding to maximum size of a pointer since all results are materialized by reference 725254721Semaste m_size = 8; 726254721Semaste m_alignment = 8; 727254721Semaste } 728254721Semaste 729254721Semaste void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err) 730254721Semaste { 731254721Semaste if (!m_is_program_reference) 732254721Semaste { 733254721Semaste if (m_temporary_allocation != LLDB_INVALID_ADDRESS) 734254721Semaste { 735254721Semaste err.SetErrorString("Trying to create a temporary region for the result but one exists"); 736254721Semaste return; 737254721Semaste } 738254721Semaste 739254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 740254721Semaste 741254721Semaste size_t byte_size = m_type.GetByteSize(); 742254721Semaste size_t bit_align = m_type.GetTypeBitAlign(); 743254721Semaste size_t byte_align = (bit_align + 7) / 8; 744254721Semaste 745254721Semaste Error alloc_error; 746254721Semaste 747254721Semaste m_temporary_allocation = map.Malloc(byte_size, byte_align, lldb::ePermissionsReadable | lldb::ePermissionsWritable, IRMemoryMap::eAllocationPolicyMirror, alloc_error); 748254721Semaste m_temporary_allocation_size = byte_size; 749254721Semaste 750254721Semaste if (!alloc_error.Success()) 751254721Semaste { 752254721Semaste err.SetErrorStringWithFormat("couldn't allocate a temporary region for the result: %s", alloc_error.AsCString()); 753254721Semaste return; 754254721Semaste } 755254721Semaste 756254721Semaste Error pointer_write_error; 757254721Semaste 758254721Semaste map.WritePointerToMemory(load_addr, m_temporary_allocation, pointer_write_error); 759254721Semaste 760254721Semaste if (!pointer_write_error.Success()) 761254721Semaste { 762254721Semaste err.SetErrorStringWithFormat("couldn't write the address of the temporary region for the result: %s", pointer_write_error.AsCString()); 763254721Semaste } 764254721Semaste } 765254721Semaste } 766254721Semaste 767254721Semaste void Dematerialize (lldb::StackFrameSP &frame_sp, 768254721Semaste IRMemoryMap &map, 769254721Semaste lldb::addr_t process_address, 770254721Semaste lldb::addr_t frame_top, 771254721Semaste lldb::addr_t frame_bottom, 772254721Semaste Error &err) 773254721Semaste { 774254721Semaste err.SetErrorString("Tried to detmaterialize a result variable with the normal Dematerialize method"); 775254721Semaste } 776254721Semaste 777254721Semaste void Dematerialize (lldb::ClangExpressionVariableSP &result_variable_sp, 778254721Semaste lldb::StackFrameSP &frame_sp, 779254721Semaste IRMemoryMap &map, 780254721Semaste lldb::addr_t process_address, 781254721Semaste lldb::addr_t frame_top, 782254721Semaste lldb::addr_t frame_bottom, 783254721Semaste Error &err) 784254721Semaste { 785254721Semaste err.Clear(); 786254721Semaste 787254721Semaste ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope(); 788254721Semaste 789254721Semaste if (!exe_scope) 790254721Semaste { 791254721Semaste err.SetErrorString("Couldn't dematerialize a result variable: invalid execution context scope"); 792254721Semaste return; 793254721Semaste } 794254721Semaste 795254721Semaste lldb::addr_t address; 796254721Semaste Error read_error; 797254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 798254721Semaste 799254721Semaste map.ReadPointerFromMemory (&address, load_addr, read_error); 800254721Semaste 801254721Semaste if (!read_error.Success()) 802254721Semaste { 803254721Semaste err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its address"); 804254721Semaste return; 805254721Semaste } 806254721Semaste 807254721Semaste lldb::TargetSP target_sp = exe_scope->CalculateTarget(); 808254721Semaste 809254721Semaste if (!target_sp) 810254721Semaste { 811254721Semaste err.SetErrorString("Couldn't dematerialize a result variable: no target"); 812254721Semaste return; 813254721Semaste } 814254721Semaste 815254721Semaste ConstString name = target_sp->GetPersistentVariables().GetNextPersistentVariableName(); 816254721Semaste 817254721Semaste lldb::ClangExpressionVariableSP ret; 818254721Semaste 819254721Semaste ret = target_sp->GetPersistentVariables().CreateVariable(exe_scope, 820254721Semaste name, 821254721Semaste m_type, 822254721Semaste map.GetByteOrder(), 823254721Semaste map.GetAddressByteSize()); 824254721Semaste 825254721Semaste if (!ret) 826254721Semaste { 827254721Semaste err.SetErrorStringWithFormat("couldn't dematerialize a result variable: failed to make persistent variable %s", name.AsCString()); 828254721Semaste return; 829254721Semaste } 830254721Semaste 831254721Semaste lldb::ProcessSP process_sp = map.GetBestExecutionContextScope()->CalculateProcess(); 832254721Semaste 833254721Semaste bool can_persist = (m_is_program_reference && process_sp && process_sp->CanJIT() && !(address >= frame_bottom && address < frame_top)); 834254721Semaste 835254721Semaste if (can_persist && m_keep_in_memory) 836254721Semaste { 837254721Semaste ret->m_live_sp = ValueObjectConstResult::Create(exe_scope, 838254721Semaste m_type, 839254721Semaste name, 840254721Semaste address, 841254721Semaste eAddressTypeLoad, 842254721Semaste ret->GetByteSize()); 843254721Semaste } 844254721Semaste 845254721Semaste ret->ValueUpdated(); 846254721Semaste 847254721Semaste const size_t pvar_byte_size = ret->GetByteSize(); 848254721Semaste uint8_t *pvar_data = ret->GetValueBytes(); 849254721Semaste 850254721Semaste map.ReadMemory(pvar_data, address, pvar_byte_size, read_error); 851254721Semaste 852254721Semaste if (!read_error.Success()) 853254721Semaste { 854254721Semaste err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its memory"); 855254721Semaste return; 856254721Semaste } 857254721Semaste 858254721Semaste result_variable_sp = ret; 859254721Semaste 860254721Semaste if (!can_persist || !m_keep_in_memory) 861254721Semaste { 862254721Semaste ret->m_flags |= ClangExpressionVariable::EVNeedsAllocation; 863254721Semaste 864254721Semaste if (m_temporary_allocation != LLDB_INVALID_ADDRESS) 865254721Semaste { 866254721Semaste Error free_error; 867254721Semaste map.Free(m_temporary_allocation, free_error); 868254721Semaste } 869254721Semaste } 870254721Semaste else 871254721Semaste { 872254721Semaste ret->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated; 873254721Semaste } 874254721Semaste 875254721Semaste m_temporary_allocation = LLDB_INVALID_ADDRESS; 876254721Semaste m_temporary_allocation_size = 0; 877254721Semaste } 878254721Semaste 879254721Semaste void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log) 880254721Semaste { 881254721Semaste StreamString dump_stream; 882254721Semaste 883254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 884254721Semaste 885254721Semaste dump_stream.Printf("0x%" PRIx64 ": EntityResultVariable\n", load_addr); 886254721Semaste 887254721Semaste Error err; 888254721Semaste 889254721Semaste lldb::addr_t ptr = LLDB_INVALID_ADDRESS; 890254721Semaste 891254721Semaste { 892254721Semaste dump_stream.Printf("Pointer:\n"); 893254721Semaste 894254721Semaste DataBufferHeap data (m_size, 0); 895254721Semaste 896254721Semaste map.ReadMemory(data.GetBytes(), load_addr, m_size, err); 897254721Semaste 898254721Semaste if (!err.Success()) 899254721Semaste { 900254721Semaste dump_stream.Printf(" <could not be read>\n"); 901254721Semaste } 902254721Semaste else 903254721Semaste { 904254721Semaste DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); 905254721Semaste 906254721Semaste extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); 907254721Semaste 908254721Semaste lldb::offset_t offset; 909254721Semaste 910254721Semaste ptr = extractor.GetPointer(&offset); 911254721Semaste 912254721Semaste dump_stream.PutChar('\n'); 913254721Semaste } 914254721Semaste } 915254721Semaste 916254721Semaste if (m_temporary_allocation == LLDB_INVALID_ADDRESS) 917254721Semaste { 918254721Semaste dump_stream.Printf("Points to process memory:\n"); 919254721Semaste } 920254721Semaste else 921254721Semaste { 922254721Semaste dump_stream.Printf("Temporary allocation:\n"); 923254721Semaste } 924254721Semaste 925254721Semaste if (ptr == LLDB_INVALID_ADDRESS) 926254721Semaste { 927254721Semaste dump_stream.Printf(" <could not be be found>\n"); 928254721Semaste } 929254721Semaste else 930254721Semaste { 931254721Semaste DataBufferHeap data (m_temporary_allocation_size, 0); 932254721Semaste 933254721Semaste map.ReadMemory(data.GetBytes(), m_temporary_allocation, m_temporary_allocation_size, err); 934254721Semaste 935254721Semaste if (!err.Success()) 936254721Semaste { 937254721Semaste dump_stream.Printf(" <could not be read>\n"); 938254721Semaste } 939254721Semaste else 940254721Semaste { 941254721Semaste DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); 942254721Semaste 943254721Semaste extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); 944254721Semaste 945254721Semaste dump_stream.PutChar('\n'); 946254721Semaste } 947254721Semaste } 948254721Semaste 949254721Semaste log->PutCString(dump_stream.GetData()); 950254721Semaste } 951254721Semaste 952254721Semaste void Wipe (IRMemoryMap &map, lldb::addr_t process_address) 953254721Semaste { 954254721Semaste if (!m_keep_in_memory && m_temporary_allocation != LLDB_INVALID_ADDRESS) 955254721Semaste { 956254721Semaste Error free_error; 957254721Semaste 958254721Semaste map.Free(m_temporary_allocation, free_error); 959254721Semaste } 960254721Semaste 961254721Semaste m_temporary_allocation = LLDB_INVALID_ADDRESS; 962254721Semaste m_temporary_allocation_size = 0; 963254721Semaste } 964254721Semasteprivate: 965254721Semaste TypeFromUser m_type; 966254721Semaste bool m_is_program_reference; 967254721Semaste bool m_keep_in_memory; 968254721Semaste 969254721Semaste lldb::addr_t m_temporary_allocation; 970254721Semaste size_t m_temporary_allocation_size; 971254721Semaste}; 972254721Semaste 973254721Semasteuint32_t 974254721SemasteMaterializer::AddResultVariable (const TypeFromUser &type, bool is_program_reference, bool keep_in_memory, Error &err) 975254721Semaste{ 976254721Semaste EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); 977254721Semaste iter->reset (new EntityResultVariable (type, is_program_reference, keep_in_memory)); 978254721Semaste uint32_t ret = AddStructMember(**iter); 979254721Semaste (*iter)->SetOffset(ret); 980254721Semaste m_result_entity = iter->get(); 981254721Semaste return ret; 982254721Semaste} 983254721Semaste 984254721Semasteclass EntitySymbol : public Materializer::Entity 985254721Semaste{ 986254721Semastepublic: 987254721Semaste EntitySymbol (const Symbol &symbol) : 988254721Semaste Entity(), 989254721Semaste m_symbol(symbol) 990254721Semaste { 991254721Semaste // Hard-coding to maximum size of a symbol 992254721Semaste m_size = 8; 993254721Semaste m_alignment = 8; 994254721Semaste } 995254721Semaste 996254721Semaste void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err) 997254721Semaste { 998254721Semaste Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); 999254721Semaste 1000254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 1001254721Semaste 1002254721Semaste if (log) 1003254721Semaste { 1004254721Semaste log->Printf("EntitySymbol::Materialize [address = 0x%" PRIx64 ", m_symbol = %s]", 1005254721Semaste (uint64_t)load_addr, 1006254721Semaste m_symbol.GetName().AsCString()); 1007254721Semaste } 1008254721Semaste 1009254721Semaste Address &sym_address = m_symbol.GetAddress(); 1010254721Semaste 1011254721Semaste ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope(); 1012254721Semaste 1013254721Semaste lldb::TargetSP target_sp; 1014254721Semaste 1015254721Semaste if (exe_scope) 1016254721Semaste target_sp = map.GetBestExecutionContextScope()->CalculateTarget(); 1017254721Semaste 1018254721Semaste if (!target_sp) 1019254721Semaste { 1020254721Semaste err.SetErrorStringWithFormat("couldn't resolve symbol %s because there is no target", m_symbol.GetName().AsCString()); 1021254721Semaste return; 1022254721Semaste } 1023254721Semaste 1024254721Semaste lldb::addr_t resolved_address = sym_address.GetLoadAddress(target_sp.get()); 1025254721Semaste 1026254721Semaste if (resolved_address == LLDB_INVALID_ADDRESS) 1027254721Semaste resolved_address = sym_address.GetFileAddress(); 1028254721Semaste 1029254721Semaste Error pointer_write_error; 1030254721Semaste 1031254721Semaste map.WritePointerToMemory(load_addr, resolved_address, pointer_write_error); 1032254721Semaste 1033254721Semaste if (!pointer_write_error.Success()) 1034254721Semaste { 1035254721Semaste err.SetErrorStringWithFormat("couldn't write the address of symbol %s: %s", m_symbol.GetName().AsCString(), pointer_write_error.AsCString()); 1036254721Semaste return; 1037254721Semaste } 1038254721Semaste } 1039254721Semaste 1040254721Semaste void Dematerialize (lldb::StackFrameSP &frame_sp, 1041254721Semaste IRMemoryMap &map, 1042254721Semaste lldb::addr_t process_address, 1043254721Semaste lldb::addr_t frame_top, 1044254721Semaste lldb::addr_t frame_bottom, 1045254721Semaste Error &err) 1046254721Semaste { 1047254721Semaste Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); 1048254721Semaste 1049254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 1050254721Semaste 1051254721Semaste if (log) 1052254721Semaste { 1053254721Semaste log->Printf("EntitySymbol::Dematerialize [address = 0x%" PRIx64 ", m_symbol = %s]", 1054254721Semaste (uint64_t)load_addr, 1055254721Semaste m_symbol.GetName().AsCString()); 1056254721Semaste } 1057254721Semaste 1058254721Semaste // no work needs to be done 1059254721Semaste } 1060254721Semaste 1061254721Semaste void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log) 1062254721Semaste { 1063254721Semaste StreamString dump_stream; 1064254721Semaste 1065254721Semaste Error err; 1066254721Semaste 1067254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 1068254721Semaste 1069254721Semaste dump_stream.Printf("0x%" PRIx64 ": EntitySymbol (%s)\n", load_addr, m_symbol.GetName().AsCString()); 1070254721Semaste 1071254721Semaste { 1072254721Semaste dump_stream.Printf("Pointer:\n"); 1073254721Semaste 1074254721Semaste DataBufferHeap data (m_size, 0); 1075254721Semaste 1076254721Semaste map.ReadMemory(data.GetBytes(), load_addr, m_size, err); 1077254721Semaste 1078254721Semaste if (!err.Success()) 1079254721Semaste { 1080254721Semaste dump_stream.Printf(" <could not be read>\n"); 1081254721Semaste } 1082254721Semaste else 1083254721Semaste { 1084254721Semaste DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); 1085254721Semaste 1086254721Semaste extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); 1087254721Semaste 1088254721Semaste dump_stream.PutChar('\n'); 1089254721Semaste } 1090254721Semaste } 1091254721Semaste 1092254721Semaste log->PutCString(dump_stream.GetData()); 1093254721Semaste } 1094254721Semaste 1095254721Semaste void Wipe (IRMemoryMap &map, lldb::addr_t process_address) 1096254721Semaste { 1097254721Semaste } 1098254721Semasteprivate: 1099254721Semaste Symbol m_symbol; 1100254721Semaste}; 1101254721Semaste 1102254721Semasteuint32_t 1103254721SemasteMaterializer::AddSymbol (const Symbol &symbol_sp, Error &err) 1104254721Semaste{ 1105254721Semaste EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); 1106254721Semaste iter->reset (new EntitySymbol (symbol_sp)); 1107254721Semaste uint32_t ret = AddStructMember(**iter); 1108254721Semaste (*iter)->SetOffset(ret); 1109254721Semaste return ret; 1110254721Semaste} 1111254721Semaste 1112254721Semasteclass EntityRegister : public Materializer::Entity 1113254721Semaste{ 1114254721Semastepublic: 1115254721Semaste EntityRegister (const RegisterInfo ®ister_info) : 1116254721Semaste Entity(), 1117254721Semaste m_register_info(register_info) 1118254721Semaste { 1119254721Semaste // Hard-coding alignment conservatively 1120254721Semaste m_size = m_register_info.byte_size; 1121254721Semaste m_alignment = m_register_info.byte_size; 1122254721Semaste } 1123254721Semaste 1124254721Semaste void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err) 1125254721Semaste { 1126254721Semaste Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); 1127254721Semaste 1128254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 1129254721Semaste 1130254721Semaste if (log) 1131254721Semaste { 1132254721Semaste log->Printf("EntityRegister::Materialize [address = 0x%" PRIx64 ", m_register_info = %s]", 1133254721Semaste (uint64_t)load_addr, 1134254721Semaste m_register_info.name); 1135254721Semaste } 1136254721Semaste 1137254721Semaste RegisterValue reg_value; 1138254721Semaste 1139254721Semaste if (!frame_sp.get()) 1140254721Semaste { 1141254721Semaste err.SetErrorStringWithFormat("couldn't materialize register %s without a stack frame", m_register_info.name); 1142254721Semaste return; 1143254721Semaste } 1144254721Semaste 1145254721Semaste lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext(); 1146254721Semaste 1147254721Semaste if (!reg_context_sp->ReadRegister(&m_register_info, reg_value)) 1148254721Semaste { 1149254721Semaste err.SetErrorStringWithFormat("couldn't read the value of register %s", m_register_info.name); 1150254721Semaste return; 1151254721Semaste } 1152254721Semaste 1153254721Semaste DataExtractor register_data; 1154254721Semaste 1155254721Semaste if (!reg_value.GetData(register_data)) 1156254721Semaste { 1157254721Semaste err.SetErrorStringWithFormat("couldn't get the data for register %s", m_register_info.name); 1158254721Semaste return; 1159254721Semaste } 1160254721Semaste 1161254721Semaste if (register_data.GetByteSize() != m_register_info.byte_size) 1162254721Semaste { 1163254721Semaste 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); 1164254721Semaste return; 1165254721Semaste } 1166254721Semaste 1167254721Semaste m_register_contents.reset(new DataBufferHeap(register_data.GetDataStart(), register_data.GetByteSize())); 1168254721Semaste 1169254721Semaste Error write_error; 1170254721Semaste 1171254721Semaste map.WriteMemory(load_addr, register_data.GetDataStart(), register_data.GetByteSize(), write_error); 1172254721Semaste 1173254721Semaste if (!write_error.Success()) 1174254721Semaste { 1175254721Semaste err.SetErrorStringWithFormat("couldn't write the contents of register %s: %s", m_register_info.name, write_error.AsCString()); 1176254721Semaste return; 1177254721Semaste } 1178254721Semaste } 1179254721Semaste 1180254721Semaste void Dematerialize (lldb::StackFrameSP &frame_sp, 1181254721Semaste IRMemoryMap &map, 1182254721Semaste lldb::addr_t process_address, 1183254721Semaste lldb::addr_t frame_top, 1184254721Semaste lldb::addr_t frame_bottom, 1185254721Semaste Error &err) 1186254721Semaste { 1187254721Semaste Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); 1188254721Semaste 1189254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 1190254721Semaste 1191254721Semaste if (log) 1192254721Semaste { 1193254721Semaste log->Printf("EntityRegister::Dematerialize [address = 0x%" PRIx64 ", m_register_info = %s]", 1194254721Semaste (uint64_t)load_addr, 1195254721Semaste m_register_info.name); 1196254721Semaste } 1197254721Semaste 1198254721Semaste Error extract_error; 1199254721Semaste 1200254721Semaste DataExtractor register_data; 1201254721Semaste 1202254721Semaste if (!frame_sp.get()) 1203254721Semaste { 1204254721Semaste err.SetErrorStringWithFormat("couldn't dematerialize register %s without a stack frame", m_register_info.name); 1205254721Semaste return; 1206254721Semaste } 1207254721Semaste 1208254721Semaste lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext(); 1209254721Semaste 1210254721Semaste map.GetMemoryData(register_data, load_addr, m_register_info.byte_size, extract_error); 1211254721Semaste 1212254721Semaste if (!extract_error.Success()) 1213254721Semaste { 1214254721Semaste err.SetErrorStringWithFormat("couldn't get the data for register %s: %s", m_register_info.name, extract_error.AsCString()); 1215254721Semaste return; 1216254721Semaste } 1217254721Semaste 1218254721Semaste if (!memcmp(register_data.GetDataStart(), m_register_contents->GetBytes(), register_data.GetByteSize())) 1219254721Semaste { 1220254721Semaste // No write required, and in particular we avoid errors if the register wasn't writable 1221254721Semaste 1222254721Semaste m_register_contents.reset(); 1223254721Semaste return; 1224254721Semaste } 1225254721Semaste 1226254721Semaste m_register_contents.reset(); 1227254721Semaste 1228254721Semaste RegisterValue register_value (const_cast<uint8_t*>(register_data.GetDataStart()), register_data.GetByteSize(), register_data.GetByteOrder()); 1229254721Semaste 1230254721Semaste if (!reg_context_sp->WriteRegister(&m_register_info, register_value)) 1231254721Semaste { 1232254721Semaste err.SetErrorStringWithFormat("couldn't write the value of register %s", m_register_info.name); 1233254721Semaste return; 1234254721Semaste } 1235254721Semaste } 1236254721Semaste 1237254721Semaste void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log) 1238254721Semaste { 1239254721Semaste StreamString dump_stream; 1240254721Semaste 1241254721Semaste Error err; 1242254721Semaste 1243254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 1244254721Semaste 1245254721Semaste 1246254721Semaste dump_stream.Printf("0x%" PRIx64 ": EntityRegister (%s)\n", load_addr, m_register_info.name); 1247254721Semaste 1248254721Semaste { 1249254721Semaste dump_stream.Printf("Value:\n"); 1250254721Semaste 1251254721Semaste DataBufferHeap data (m_size, 0); 1252254721Semaste 1253254721Semaste map.ReadMemory(data.GetBytes(), load_addr, m_size, err); 1254254721Semaste 1255254721Semaste if (!err.Success()) 1256254721Semaste { 1257254721Semaste dump_stream.Printf(" <could not be read>\n"); 1258254721Semaste } 1259254721Semaste else 1260254721Semaste { 1261254721Semaste DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); 1262254721Semaste 1263254721Semaste extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); 1264254721Semaste 1265254721Semaste dump_stream.PutChar('\n'); 1266254721Semaste } 1267254721Semaste } 1268254721Semaste 1269254721Semaste log->PutCString(dump_stream.GetData()); 1270254721Semaste } 1271254721Semaste 1272254721Semaste void Wipe (IRMemoryMap &map, lldb::addr_t process_address) 1273254721Semaste { 1274254721Semaste } 1275254721Semasteprivate: 1276254721Semaste RegisterInfo m_register_info; 1277254721Semaste lldb::DataBufferSP m_register_contents; 1278254721Semaste}; 1279254721Semaste 1280254721Semasteuint32_t 1281254721SemasteMaterializer::AddRegister (const RegisterInfo ®ister_info, Error &err) 1282254721Semaste{ 1283254721Semaste EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); 1284254721Semaste iter->reset (new EntityRegister (register_info)); 1285254721Semaste uint32_t ret = AddStructMember(**iter); 1286254721Semaste (*iter)->SetOffset(ret); 1287254721Semaste return ret; 1288254721Semaste} 1289254721Semaste 1290254721SemasteMaterializer::Materializer () : 1291254721Semaste m_dematerializer_wp(), 1292254721Semaste m_result_entity(NULL), 1293254721Semaste m_current_offset(0), 1294254721Semaste m_struct_alignment(8) 1295254721Semaste{ 1296254721Semaste} 1297254721Semaste 1298254721SemasteMaterializer::~Materializer () 1299254721Semaste{ 1300254721Semaste DematerializerSP dematerializer_sp = m_dematerializer_wp.lock(); 1301254721Semaste 1302254721Semaste if (dematerializer_sp) 1303254721Semaste dematerializer_sp->Wipe(); 1304254721Semaste} 1305254721Semaste 1306254721SemasteMaterializer::DematerializerSP 1307254721SemasteMaterializer::Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &error) 1308254721Semaste{ 1309254721Semaste ExecutionContextScope *exe_scope = frame_sp.get(); 1310254721Semaste 1311254721Semaste if (!exe_scope) 1312254721Semaste exe_scope = map.GetBestExecutionContextScope(); 1313254721Semaste 1314254721Semaste DematerializerSP dematerializer_sp = m_dematerializer_wp.lock(); 1315254721Semaste 1316254721Semaste if (dematerializer_sp) 1317254721Semaste { 1318254721Semaste error.SetErrorToGenericError(); 1319254721Semaste error.SetErrorString("Couldn't materialize: already materialized"); 1320254721Semaste } 1321254721Semaste 1322254721Semaste DematerializerSP ret(new Dematerializer(*this, frame_sp, map, process_address)); 1323254721Semaste 1324254721Semaste if (!exe_scope) 1325254721Semaste { 1326254721Semaste error.SetErrorToGenericError(); 1327254721Semaste error.SetErrorString("Couldn't materialize: target doesn't exist"); 1328254721Semaste } 1329254721Semaste 1330254721Semaste for (EntityUP &entity_up : m_entities) 1331254721Semaste { 1332254721Semaste entity_up->Materialize(frame_sp, map, process_address, error); 1333254721Semaste 1334254721Semaste if (!error.Success()) 1335254721Semaste return DematerializerSP(); 1336254721Semaste } 1337254721Semaste 1338254721Semaste if (Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) 1339254721Semaste { 1340254721Semaste log->Printf("Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64 ") materialized:", frame_sp.get(), process_address); 1341254721Semaste for (EntityUP &entity_up : m_entities) 1342254721Semaste entity_up->DumpToLog(map, process_address, log); 1343254721Semaste } 1344254721Semaste 1345254721Semaste m_dematerializer_wp = ret; 1346254721Semaste 1347254721Semaste return ret; 1348254721Semaste} 1349254721Semaste 1350254721Semastevoid 1351254721SemasteMaterializer::Dematerializer::Dematerialize (Error &error, lldb::ClangExpressionVariableSP &result_sp, lldb::addr_t frame_bottom, lldb::addr_t frame_top) 1352254721Semaste{ 1353254721Semaste lldb::StackFrameSP frame_sp; 1354254721Semaste 1355254721Semaste lldb::ThreadSP thread_sp = m_thread_wp.lock(); 1356254721Semaste if (thread_sp) 1357254721Semaste frame_sp = thread_sp->GetFrameWithStackID(m_stack_id); 1358254721Semaste 1359254721Semaste ExecutionContextScope *exe_scope = m_map->GetBestExecutionContextScope(); 1360254721Semaste 1361254721Semaste if (!IsValid()) 1362254721Semaste { 1363254721Semaste error.SetErrorToGenericError(); 1364254721Semaste error.SetErrorString("Couldn't dematerialize: invalid dematerializer"); 1365254721Semaste } 1366254721Semaste 1367254721Semaste if (!exe_scope) 1368254721Semaste { 1369254721Semaste error.SetErrorToGenericError(); 1370254721Semaste error.SetErrorString("Couldn't dematerialize: target is gone"); 1371254721Semaste } 1372254721Semaste else 1373254721Semaste { 1374254721Semaste if (Log *log =lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) 1375254721Semaste { 1376254721Semaste log->Printf("Materializer::Dematerialize (frame_sp = %p, process_address = 0x%" PRIx64 ") about to dematerialize:", frame_sp.get(), m_process_address); 1377254721Semaste for (EntityUP &entity_up : m_materializer->m_entities) 1378254721Semaste entity_up->DumpToLog(*m_map, m_process_address, log); 1379254721Semaste } 1380254721Semaste 1381254721Semaste for (EntityUP &entity_up : m_materializer->m_entities) 1382254721Semaste { 1383254721Semaste if (entity_up.get() == m_materializer->m_result_entity) 1384254721Semaste { 1385254721Semaste static_cast<EntityResultVariable*>(m_materializer->m_result_entity)->Dematerialize (result_sp, frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error); 1386254721Semaste } 1387254721Semaste else 1388254721Semaste { 1389254721Semaste entity_up->Dematerialize (frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error); 1390254721Semaste } 1391254721Semaste 1392254721Semaste if (!error.Success()) 1393254721Semaste break; 1394254721Semaste } 1395254721Semaste } 1396254721Semaste 1397254721Semaste Wipe(); 1398254721Semaste} 1399254721Semaste 1400254721Semastevoid 1401254721SemasteMaterializer::Dematerializer::Wipe () 1402254721Semaste{ 1403254721Semaste if (!IsValid()) 1404254721Semaste return; 1405254721Semaste 1406254721Semaste for (EntityUP &entity_up : m_materializer->m_entities) 1407254721Semaste { 1408254721Semaste entity_up->Wipe (*m_map, m_process_address); 1409254721Semaste } 1410254721Semaste 1411254721Semaste m_materializer = NULL; 1412254721Semaste m_map = NULL; 1413254721Semaste m_process_address = LLDB_INVALID_ADDRESS; 1414254721Semaste} 1415