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 { 464269024Semaste AddressType address_type = eAddressTypeInvalid; 465269024Semaste const bool scalar_is_load_address = false; 466269024Semaste lldb::addr_t addr_of_valobj = valobj_sp->GetAddressOf(scalar_is_load_address, &address_type); 467263363Semaste if (addr_of_valobj != LLDB_INVALID_ADDRESS) 468254721Semaste { 469254721Semaste Error write_error; 470263363Semaste map.WritePointerToMemory(load_addr, addr_of_valobj, write_error); 471254721Semaste 472254721Semaste if (!write_error.Success()) 473254721Semaste { 474254721Semaste err.SetErrorStringWithFormat("couldn't write the address of variable %s to memory: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString()); 475254721Semaste return; 476254721Semaste } 477254721Semaste } 478254721Semaste else 479254721Semaste { 480254721Semaste DataExtractor data; 481254721Semaste valobj_sp->GetData(data); 482254721Semaste 483254721Semaste if (m_temporary_allocation != LLDB_INVALID_ADDRESS) 484254721Semaste { 485254721Semaste err.SetErrorStringWithFormat("trying to create a temporary region for %s but one exists", m_variable_sp->GetName().AsCString()); 486254721Semaste return; 487254721Semaste } 488254721Semaste 489254721Semaste if (data.GetByteSize() != m_variable_sp->GetType()->GetByteSize()) 490254721Semaste { 491254721Semaste if (data.GetByteSize() == 0 && m_variable_sp->LocationExpression().IsValid() == false) 492254721Semaste { 493254721Semaste err.SetErrorStringWithFormat("the variable '%s' has no location, it may have been optimized out", m_variable_sp->GetName().AsCString()); 494254721Semaste } 495254721Semaste else 496254721Semaste { 497263367Semaste err.SetErrorStringWithFormat("size of variable %s (%" PRIu64 ") disagrees with the ValueObject's size (%" PRIu64 ")", 498263367Semaste m_variable_sp->GetName().AsCString(), 499263367Semaste m_variable_sp->GetType()->GetByteSize(), 500263367Semaste data.GetByteSize()); 501254721Semaste } 502254721Semaste return; 503254721Semaste } 504254721Semaste 505254721Semaste size_t bit_align = m_variable_sp->GetType()->GetClangLayoutType().GetTypeBitAlign(); 506254721Semaste size_t byte_align = (bit_align + 7) / 8; 507254721Semaste 508269024Semaste if (!byte_align) 509269024Semaste byte_align = 1; 510269024Semaste 511254721Semaste Error alloc_error; 512254721Semaste 513254721Semaste m_temporary_allocation = map.Malloc(data.GetByteSize(), byte_align, lldb::ePermissionsReadable | lldb::ePermissionsWritable, IRMemoryMap::eAllocationPolicyMirror, alloc_error); 514254721Semaste m_temporary_allocation_size = data.GetByteSize(); 515254721Semaste 516254721Semaste if (!alloc_error.Success()) 517254721Semaste { 518254721Semaste err.SetErrorStringWithFormat("couldn't allocate a temporary region for %s: %s", m_variable_sp->GetName().AsCString(), alloc_error.AsCString()); 519254721Semaste return; 520254721Semaste } 521254721Semaste 522254721Semaste Error write_error; 523254721Semaste 524254721Semaste map.WriteMemory(m_temporary_allocation, data.GetDataStart(), data.GetByteSize(), write_error); 525254721Semaste 526254721Semaste if (!write_error.Success()) 527254721Semaste { 528254721Semaste err.SetErrorStringWithFormat("couldn't write to the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString()); 529254721Semaste return; 530254721Semaste } 531254721Semaste 532254721Semaste Error pointer_write_error; 533254721Semaste 534254721Semaste map.WritePointerToMemory(load_addr, m_temporary_allocation, pointer_write_error); 535254721Semaste 536254721Semaste if (!pointer_write_error.Success()) 537254721Semaste { 538254721Semaste err.SetErrorStringWithFormat("couldn't write the address of the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), pointer_write_error.AsCString()); 539254721Semaste } 540254721Semaste } 541254721Semaste } 542254721Semaste } 543254721Semaste 544254721Semaste void Dematerialize (lldb::StackFrameSP &frame_sp, 545254721Semaste IRMemoryMap &map, 546254721Semaste lldb::addr_t process_address, 547254721Semaste lldb::addr_t frame_top, 548254721Semaste lldb::addr_t frame_bottom, 549254721Semaste Error &err) 550254721Semaste { 551254721Semaste Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); 552254721Semaste 553254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 554254721Semaste if (log) 555254721Semaste { 556254721Semaste log->Printf("EntityVariable::Dematerialize [address = 0x%" PRIx64 ", m_variable_sp = %s]", 557254721Semaste (uint64_t)load_addr, 558254721Semaste m_variable_sp->GetName().AsCString()); 559254721Semaste } 560254721Semaste 561254721Semaste if (m_temporary_allocation != LLDB_INVALID_ADDRESS) 562254721Semaste { 563254721Semaste ExecutionContextScope *scope = frame_sp.get(); 564254721Semaste 565254721Semaste if (!scope) 566254721Semaste scope = map.GetBestExecutionContextScope(); 567254721Semaste 568254721Semaste lldb::ValueObjectSP valobj_sp = ValueObjectVariable::Create(scope, m_variable_sp); 569254721Semaste 570254721Semaste if (!valobj_sp) 571254721Semaste { 572254721Semaste err.SetErrorStringWithFormat("couldn't get a value object for variable %s", m_variable_sp->GetName().AsCString()); 573254721Semaste return; 574254721Semaste } 575254721Semaste 576254721Semaste lldb_private::DataExtractor data; 577254721Semaste 578254721Semaste Error extract_error; 579254721Semaste 580254721Semaste map.GetMemoryData(data, m_temporary_allocation, valobj_sp->GetByteSize(), extract_error); 581254721Semaste 582254721Semaste if (!extract_error.Success()) 583254721Semaste { 584254721Semaste err.SetErrorStringWithFormat("couldn't get the data for variable %s", m_variable_sp->GetName().AsCString()); 585254721Semaste return; 586254721Semaste } 587254721Semaste 588254721Semaste Error set_error; 589254721Semaste 590254721Semaste valobj_sp->SetData(data, set_error); 591254721Semaste 592254721Semaste if (!set_error.Success()) 593254721Semaste { 594254721Semaste err.SetErrorStringWithFormat("couldn't write the new contents of %s back into the variable", m_variable_sp->GetName().AsCString()); 595254721Semaste return; 596254721Semaste } 597254721Semaste 598254721Semaste Error free_error; 599254721Semaste 600254721Semaste map.Free(m_temporary_allocation, free_error); 601254721Semaste 602254721Semaste if (!free_error.Success()) 603254721Semaste { 604254721Semaste err.SetErrorStringWithFormat("couldn't free the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), free_error.AsCString()); 605254721Semaste return; 606254721Semaste } 607254721Semaste 608254721Semaste m_temporary_allocation = LLDB_INVALID_ADDRESS; 609254721Semaste m_temporary_allocation_size = 0; 610254721Semaste } 611254721Semaste } 612254721Semaste 613254721Semaste void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log) 614254721Semaste { 615254721Semaste StreamString dump_stream; 616254721Semaste 617254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 618254721Semaste dump_stream.Printf("0x%" PRIx64 ": EntityVariable\n", load_addr); 619254721Semaste 620254721Semaste Error err; 621254721Semaste 622254721Semaste lldb::addr_t ptr = LLDB_INVALID_ADDRESS; 623254721Semaste 624254721Semaste { 625254721Semaste dump_stream.Printf("Pointer:\n"); 626254721Semaste 627254721Semaste DataBufferHeap data (m_size, 0); 628254721Semaste 629254721Semaste map.ReadMemory(data.GetBytes(), load_addr, m_size, err); 630254721Semaste 631254721Semaste if (!err.Success()) 632254721Semaste { 633254721Semaste dump_stream.Printf(" <could not be read>\n"); 634254721Semaste } 635254721Semaste else 636254721Semaste { 637254721Semaste DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); 638254721Semaste 639254721Semaste extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); 640254721Semaste 641254721Semaste lldb::offset_t offset; 642254721Semaste 643254721Semaste ptr = extractor.GetPointer(&offset); 644254721Semaste 645254721Semaste dump_stream.PutChar('\n'); 646254721Semaste } 647254721Semaste } 648254721Semaste 649254721Semaste if (m_temporary_allocation == LLDB_INVALID_ADDRESS) 650254721Semaste { 651254721Semaste dump_stream.Printf("Points to process memory:\n"); 652254721Semaste } 653254721Semaste else 654254721Semaste { 655254721Semaste dump_stream.Printf("Temporary allocation:\n"); 656254721Semaste } 657254721Semaste 658254721Semaste if (ptr == LLDB_INVALID_ADDRESS) 659254721Semaste { 660254721Semaste dump_stream.Printf(" <could not be be found>\n"); 661254721Semaste } 662254721Semaste else 663254721Semaste { 664254721Semaste DataBufferHeap data (m_temporary_allocation_size, 0); 665254721Semaste 666254721Semaste map.ReadMemory(data.GetBytes(), m_temporary_allocation, m_temporary_allocation_size, err); 667254721Semaste 668254721Semaste if (!err.Success()) 669254721Semaste { 670254721Semaste dump_stream.Printf(" <could not be read>\n"); 671254721Semaste } 672254721Semaste else 673254721Semaste { 674254721Semaste DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); 675254721Semaste 676254721Semaste extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); 677254721Semaste 678254721Semaste dump_stream.PutChar('\n'); 679254721Semaste } 680254721Semaste } 681254721Semaste 682254721Semaste log->PutCString(dump_stream.GetData()); 683254721Semaste } 684254721Semaste 685254721Semaste void Wipe (IRMemoryMap &map, lldb::addr_t process_address) 686254721Semaste { 687254721Semaste if (m_temporary_allocation != LLDB_INVALID_ADDRESS) 688254721Semaste { 689254721Semaste Error free_error; 690254721Semaste 691254721Semaste map.Free(m_temporary_allocation, free_error); 692254721Semaste 693254721Semaste m_temporary_allocation = LLDB_INVALID_ADDRESS; 694254721Semaste m_temporary_allocation_size = 0; 695254721Semaste } 696254721Semaste 697254721Semaste } 698254721Semasteprivate: 699254721Semaste lldb::VariableSP m_variable_sp; 700254721Semaste bool m_is_reference; 701254721Semaste lldb::addr_t m_temporary_allocation; 702254721Semaste size_t m_temporary_allocation_size; 703254721Semaste}; 704254721Semaste 705254721Semasteuint32_t 706254721SemasteMaterializer::AddVariable (lldb::VariableSP &variable_sp, Error &err) 707254721Semaste{ 708254721Semaste EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); 709254721Semaste iter->reset (new EntityVariable (variable_sp)); 710254721Semaste uint32_t ret = AddStructMember(**iter); 711254721Semaste (*iter)->SetOffset(ret); 712254721Semaste return ret; 713254721Semaste} 714254721Semaste 715254721Semasteclass EntityResultVariable : public Materializer::Entity 716254721Semaste{ 717254721Semastepublic: 718254721Semaste EntityResultVariable (const TypeFromUser &type, bool is_program_reference, bool keep_in_memory) : 719254721Semaste Entity(), 720254721Semaste m_type(type), 721254721Semaste m_is_program_reference(is_program_reference), 722254721Semaste m_keep_in_memory(keep_in_memory), 723254721Semaste m_temporary_allocation(LLDB_INVALID_ADDRESS), 724254721Semaste m_temporary_allocation_size(0) 725254721Semaste { 726254721Semaste // Hard-coding to maximum size of a pointer since all results are materialized by reference 727254721Semaste m_size = 8; 728254721Semaste m_alignment = 8; 729254721Semaste } 730254721Semaste 731254721Semaste void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err) 732254721Semaste { 733254721Semaste if (!m_is_program_reference) 734254721Semaste { 735254721Semaste if (m_temporary_allocation != LLDB_INVALID_ADDRESS) 736254721Semaste { 737254721Semaste err.SetErrorString("Trying to create a temporary region for the result but one exists"); 738254721Semaste return; 739254721Semaste } 740254721Semaste 741254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 742254721Semaste 743254721Semaste size_t byte_size = m_type.GetByteSize(); 744254721Semaste size_t bit_align = m_type.GetTypeBitAlign(); 745254721Semaste size_t byte_align = (bit_align + 7) / 8; 746254721Semaste 747269024Semaste if (!byte_align) 748269024Semaste byte_align = 1; 749269024Semaste 750254721Semaste Error alloc_error; 751254721Semaste 752254721Semaste m_temporary_allocation = map.Malloc(byte_size, byte_align, lldb::ePermissionsReadable | lldb::ePermissionsWritable, IRMemoryMap::eAllocationPolicyMirror, alloc_error); 753254721Semaste m_temporary_allocation_size = byte_size; 754254721Semaste 755254721Semaste if (!alloc_error.Success()) 756254721Semaste { 757254721Semaste err.SetErrorStringWithFormat("couldn't allocate a temporary region for the result: %s", alloc_error.AsCString()); 758254721Semaste return; 759254721Semaste } 760254721Semaste 761254721Semaste Error pointer_write_error; 762254721Semaste 763254721Semaste map.WritePointerToMemory(load_addr, m_temporary_allocation, pointer_write_error); 764254721Semaste 765254721Semaste if (!pointer_write_error.Success()) 766254721Semaste { 767254721Semaste err.SetErrorStringWithFormat("couldn't write the address of the temporary region for the result: %s", pointer_write_error.AsCString()); 768254721Semaste } 769254721Semaste } 770254721Semaste } 771254721Semaste 772254721Semaste void Dematerialize (lldb::StackFrameSP &frame_sp, 773254721Semaste IRMemoryMap &map, 774254721Semaste lldb::addr_t process_address, 775254721Semaste lldb::addr_t frame_top, 776254721Semaste lldb::addr_t frame_bottom, 777254721Semaste Error &err) 778254721Semaste { 779254721Semaste err.SetErrorString("Tried to detmaterialize a result variable with the normal Dematerialize method"); 780254721Semaste } 781254721Semaste 782254721Semaste void Dematerialize (lldb::ClangExpressionVariableSP &result_variable_sp, 783254721Semaste lldb::StackFrameSP &frame_sp, 784254721Semaste IRMemoryMap &map, 785254721Semaste lldb::addr_t process_address, 786254721Semaste lldb::addr_t frame_top, 787254721Semaste lldb::addr_t frame_bottom, 788254721Semaste Error &err) 789254721Semaste { 790254721Semaste err.Clear(); 791254721Semaste 792254721Semaste ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope(); 793254721Semaste 794254721Semaste if (!exe_scope) 795254721Semaste { 796254721Semaste err.SetErrorString("Couldn't dematerialize a result variable: invalid execution context scope"); 797254721Semaste return; 798254721Semaste } 799254721Semaste 800254721Semaste lldb::addr_t address; 801254721Semaste Error read_error; 802254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 803254721Semaste 804254721Semaste map.ReadPointerFromMemory (&address, load_addr, read_error); 805254721Semaste 806254721Semaste if (!read_error.Success()) 807254721Semaste { 808254721Semaste err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its address"); 809254721Semaste return; 810254721Semaste } 811254721Semaste 812254721Semaste lldb::TargetSP target_sp = exe_scope->CalculateTarget(); 813254721Semaste 814254721Semaste if (!target_sp) 815254721Semaste { 816254721Semaste err.SetErrorString("Couldn't dematerialize a result variable: no target"); 817254721Semaste return; 818254721Semaste } 819254721Semaste 820254721Semaste ConstString name = target_sp->GetPersistentVariables().GetNextPersistentVariableName(); 821254721Semaste 822254721Semaste lldb::ClangExpressionVariableSP ret; 823254721Semaste 824254721Semaste ret = target_sp->GetPersistentVariables().CreateVariable(exe_scope, 825254721Semaste name, 826254721Semaste m_type, 827254721Semaste map.GetByteOrder(), 828254721Semaste map.GetAddressByteSize()); 829254721Semaste 830254721Semaste if (!ret) 831254721Semaste { 832254721Semaste err.SetErrorStringWithFormat("couldn't dematerialize a result variable: failed to make persistent variable %s", name.AsCString()); 833254721Semaste return; 834254721Semaste } 835254721Semaste 836254721Semaste lldb::ProcessSP process_sp = map.GetBestExecutionContextScope()->CalculateProcess(); 837254721Semaste 838254721Semaste bool can_persist = (m_is_program_reference && process_sp && process_sp->CanJIT() && !(address >= frame_bottom && address < frame_top)); 839254721Semaste 840254721Semaste if (can_persist && m_keep_in_memory) 841254721Semaste { 842254721Semaste ret->m_live_sp = ValueObjectConstResult::Create(exe_scope, 843254721Semaste m_type, 844254721Semaste name, 845254721Semaste address, 846254721Semaste eAddressTypeLoad, 847263363Semaste map.GetAddressByteSize()); 848254721Semaste } 849254721Semaste 850254721Semaste ret->ValueUpdated(); 851254721Semaste 852254721Semaste const size_t pvar_byte_size = ret->GetByteSize(); 853254721Semaste uint8_t *pvar_data = ret->GetValueBytes(); 854254721Semaste 855254721Semaste map.ReadMemory(pvar_data, address, pvar_byte_size, read_error); 856254721Semaste 857254721Semaste if (!read_error.Success()) 858254721Semaste { 859254721Semaste err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its memory"); 860254721Semaste return; 861254721Semaste } 862254721Semaste 863254721Semaste result_variable_sp = ret; 864254721Semaste 865254721Semaste if (!can_persist || !m_keep_in_memory) 866254721Semaste { 867254721Semaste ret->m_flags |= ClangExpressionVariable::EVNeedsAllocation; 868254721Semaste 869254721Semaste if (m_temporary_allocation != LLDB_INVALID_ADDRESS) 870254721Semaste { 871254721Semaste Error free_error; 872254721Semaste map.Free(m_temporary_allocation, free_error); 873254721Semaste } 874254721Semaste } 875254721Semaste else 876254721Semaste { 877254721Semaste ret->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated; 878254721Semaste } 879254721Semaste 880254721Semaste m_temporary_allocation = LLDB_INVALID_ADDRESS; 881254721Semaste m_temporary_allocation_size = 0; 882254721Semaste } 883254721Semaste 884254721Semaste void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log) 885254721Semaste { 886254721Semaste StreamString dump_stream; 887254721Semaste 888254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 889254721Semaste 890254721Semaste dump_stream.Printf("0x%" PRIx64 ": EntityResultVariable\n", load_addr); 891254721Semaste 892254721Semaste Error err; 893254721Semaste 894254721Semaste lldb::addr_t ptr = LLDB_INVALID_ADDRESS; 895254721Semaste 896254721Semaste { 897254721Semaste dump_stream.Printf("Pointer:\n"); 898254721Semaste 899254721Semaste DataBufferHeap data (m_size, 0); 900254721Semaste 901254721Semaste map.ReadMemory(data.GetBytes(), load_addr, m_size, err); 902254721Semaste 903254721Semaste if (!err.Success()) 904254721Semaste { 905254721Semaste dump_stream.Printf(" <could not be read>\n"); 906254721Semaste } 907254721Semaste else 908254721Semaste { 909254721Semaste DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); 910254721Semaste 911254721Semaste extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); 912254721Semaste 913254721Semaste lldb::offset_t offset; 914254721Semaste 915254721Semaste ptr = extractor.GetPointer(&offset); 916254721Semaste 917254721Semaste dump_stream.PutChar('\n'); 918254721Semaste } 919254721Semaste } 920254721Semaste 921254721Semaste if (m_temporary_allocation == LLDB_INVALID_ADDRESS) 922254721Semaste { 923254721Semaste dump_stream.Printf("Points to process memory:\n"); 924254721Semaste } 925254721Semaste else 926254721Semaste { 927254721Semaste dump_stream.Printf("Temporary allocation:\n"); 928254721Semaste } 929254721Semaste 930254721Semaste if (ptr == LLDB_INVALID_ADDRESS) 931254721Semaste { 932254721Semaste dump_stream.Printf(" <could not be be found>\n"); 933254721Semaste } 934254721Semaste else 935254721Semaste { 936254721Semaste DataBufferHeap data (m_temporary_allocation_size, 0); 937254721Semaste 938254721Semaste map.ReadMemory(data.GetBytes(), m_temporary_allocation, m_temporary_allocation_size, err); 939254721Semaste 940254721Semaste if (!err.Success()) 941254721Semaste { 942254721Semaste dump_stream.Printf(" <could not be read>\n"); 943254721Semaste } 944254721Semaste else 945254721Semaste { 946254721Semaste DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); 947254721Semaste 948254721Semaste extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); 949254721Semaste 950254721Semaste dump_stream.PutChar('\n'); 951254721Semaste } 952254721Semaste } 953254721Semaste 954254721Semaste log->PutCString(dump_stream.GetData()); 955254721Semaste } 956254721Semaste 957254721Semaste void Wipe (IRMemoryMap &map, lldb::addr_t process_address) 958254721Semaste { 959254721Semaste if (!m_keep_in_memory && m_temporary_allocation != LLDB_INVALID_ADDRESS) 960254721Semaste { 961254721Semaste Error free_error; 962254721Semaste 963254721Semaste map.Free(m_temporary_allocation, free_error); 964254721Semaste } 965254721Semaste 966254721Semaste m_temporary_allocation = LLDB_INVALID_ADDRESS; 967254721Semaste m_temporary_allocation_size = 0; 968254721Semaste } 969254721Semasteprivate: 970254721Semaste TypeFromUser m_type; 971254721Semaste bool m_is_program_reference; 972254721Semaste bool m_keep_in_memory; 973254721Semaste 974254721Semaste lldb::addr_t m_temporary_allocation; 975254721Semaste size_t m_temporary_allocation_size; 976254721Semaste}; 977254721Semaste 978254721Semasteuint32_t 979254721SemasteMaterializer::AddResultVariable (const TypeFromUser &type, bool is_program_reference, bool keep_in_memory, Error &err) 980254721Semaste{ 981254721Semaste EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); 982254721Semaste iter->reset (new EntityResultVariable (type, is_program_reference, keep_in_memory)); 983254721Semaste uint32_t ret = AddStructMember(**iter); 984254721Semaste (*iter)->SetOffset(ret); 985254721Semaste m_result_entity = iter->get(); 986254721Semaste return ret; 987254721Semaste} 988254721Semaste 989254721Semasteclass EntitySymbol : public Materializer::Entity 990254721Semaste{ 991254721Semastepublic: 992254721Semaste EntitySymbol (const Symbol &symbol) : 993254721Semaste Entity(), 994254721Semaste m_symbol(symbol) 995254721Semaste { 996254721Semaste // Hard-coding to maximum size of a symbol 997254721Semaste m_size = 8; 998254721Semaste m_alignment = 8; 999254721Semaste } 1000254721Semaste 1001254721Semaste void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err) 1002254721Semaste { 1003254721Semaste Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); 1004254721Semaste 1005254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 1006254721Semaste 1007254721Semaste if (log) 1008254721Semaste { 1009254721Semaste log->Printf("EntitySymbol::Materialize [address = 0x%" PRIx64 ", m_symbol = %s]", 1010254721Semaste (uint64_t)load_addr, 1011254721Semaste m_symbol.GetName().AsCString()); 1012254721Semaste } 1013254721Semaste 1014254721Semaste Address &sym_address = m_symbol.GetAddress(); 1015254721Semaste 1016254721Semaste ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope(); 1017254721Semaste 1018254721Semaste lldb::TargetSP target_sp; 1019254721Semaste 1020254721Semaste if (exe_scope) 1021254721Semaste target_sp = map.GetBestExecutionContextScope()->CalculateTarget(); 1022254721Semaste 1023254721Semaste if (!target_sp) 1024254721Semaste { 1025254721Semaste err.SetErrorStringWithFormat("couldn't resolve symbol %s because there is no target", m_symbol.GetName().AsCString()); 1026254721Semaste return; 1027254721Semaste } 1028254721Semaste 1029254721Semaste lldb::addr_t resolved_address = sym_address.GetLoadAddress(target_sp.get()); 1030254721Semaste 1031254721Semaste if (resolved_address == LLDB_INVALID_ADDRESS) 1032254721Semaste resolved_address = sym_address.GetFileAddress(); 1033254721Semaste 1034254721Semaste Error pointer_write_error; 1035254721Semaste 1036254721Semaste map.WritePointerToMemory(load_addr, resolved_address, pointer_write_error); 1037254721Semaste 1038254721Semaste if (!pointer_write_error.Success()) 1039254721Semaste { 1040254721Semaste err.SetErrorStringWithFormat("couldn't write the address of symbol %s: %s", m_symbol.GetName().AsCString(), pointer_write_error.AsCString()); 1041254721Semaste return; 1042254721Semaste } 1043254721Semaste } 1044254721Semaste 1045254721Semaste void Dematerialize (lldb::StackFrameSP &frame_sp, 1046254721Semaste IRMemoryMap &map, 1047254721Semaste lldb::addr_t process_address, 1048254721Semaste lldb::addr_t frame_top, 1049254721Semaste lldb::addr_t frame_bottom, 1050254721Semaste Error &err) 1051254721Semaste { 1052254721Semaste Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); 1053254721Semaste 1054254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 1055254721Semaste 1056254721Semaste if (log) 1057254721Semaste { 1058254721Semaste log->Printf("EntitySymbol::Dematerialize [address = 0x%" PRIx64 ", m_symbol = %s]", 1059254721Semaste (uint64_t)load_addr, 1060254721Semaste m_symbol.GetName().AsCString()); 1061254721Semaste } 1062254721Semaste 1063254721Semaste // no work needs to be done 1064254721Semaste } 1065254721Semaste 1066254721Semaste void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log) 1067254721Semaste { 1068254721Semaste StreamString dump_stream; 1069254721Semaste 1070254721Semaste Error err; 1071254721Semaste 1072254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 1073254721Semaste 1074254721Semaste dump_stream.Printf("0x%" PRIx64 ": EntitySymbol (%s)\n", load_addr, m_symbol.GetName().AsCString()); 1075254721Semaste 1076254721Semaste { 1077254721Semaste dump_stream.Printf("Pointer:\n"); 1078254721Semaste 1079254721Semaste DataBufferHeap data (m_size, 0); 1080254721Semaste 1081254721Semaste map.ReadMemory(data.GetBytes(), load_addr, m_size, err); 1082254721Semaste 1083254721Semaste if (!err.Success()) 1084254721Semaste { 1085254721Semaste dump_stream.Printf(" <could not be read>\n"); 1086254721Semaste } 1087254721Semaste else 1088254721Semaste { 1089254721Semaste DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); 1090254721Semaste 1091254721Semaste extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); 1092254721Semaste 1093254721Semaste dump_stream.PutChar('\n'); 1094254721Semaste } 1095254721Semaste } 1096254721Semaste 1097254721Semaste log->PutCString(dump_stream.GetData()); 1098254721Semaste } 1099254721Semaste 1100254721Semaste void Wipe (IRMemoryMap &map, lldb::addr_t process_address) 1101254721Semaste { 1102254721Semaste } 1103254721Semasteprivate: 1104254721Semaste Symbol m_symbol; 1105254721Semaste}; 1106254721Semaste 1107254721Semasteuint32_t 1108254721SemasteMaterializer::AddSymbol (const Symbol &symbol_sp, Error &err) 1109254721Semaste{ 1110254721Semaste EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); 1111254721Semaste iter->reset (new EntitySymbol (symbol_sp)); 1112254721Semaste uint32_t ret = AddStructMember(**iter); 1113254721Semaste (*iter)->SetOffset(ret); 1114254721Semaste return ret; 1115254721Semaste} 1116254721Semaste 1117254721Semasteclass EntityRegister : public Materializer::Entity 1118254721Semaste{ 1119254721Semastepublic: 1120254721Semaste EntityRegister (const RegisterInfo ®ister_info) : 1121254721Semaste Entity(), 1122254721Semaste m_register_info(register_info) 1123254721Semaste { 1124254721Semaste // Hard-coding alignment conservatively 1125254721Semaste m_size = m_register_info.byte_size; 1126254721Semaste m_alignment = m_register_info.byte_size; 1127254721Semaste } 1128254721Semaste 1129254721Semaste void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err) 1130254721Semaste { 1131254721Semaste Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); 1132254721Semaste 1133254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 1134254721Semaste 1135254721Semaste if (log) 1136254721Semaste { 1137254721Semaste log->Printf("EntityRegister::Materialize [address = 0x%" PRIx64 ", m_register_info = %s]", 1138254721Semaste (uint64_t)load_addr, 1139254721Semaste m_register_info.name); 1140254721Semaste } 1141254721Semaste 1142254721Semaste RegisterValue reg_value; 1143254721Semaste 1144254721Semaste if (!frame_sp.get()) 1145254721Semaste { 1146254721Semaste err.SetErrorStringWithFormat("couldn't materialize register %s without a stack frame", m_register_info.name); 1147254721Semaste return; 1148254721Semaste } 1149254721Semaste 1150254721Semaste lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext(); 1151254721Semaste 1152254721Semaste if (!reg_context_sp->ReadRegister(&m_register_info, reg_value)) 1153254721Semaste { 1154254721Semaste err.SetErrorStringWithFormat("couldn't read the value of register %s", m_register_info.name); 1155254721Semaste return; 1156254721Semaste } 1157254721Semaste 1158254721Semaste DataExtractor register_data; 1159254721Semaste 1160254721Semaste if (!reg_value.GetData(register_data)) 1161254721Semaste { 1162254721Semaste err.SetErrorStringWithFormat("couldn't get the data for register %s", m_register_info.name); 1163254721Semaste return; 1164254721Semaste } 1165254721Semaste 1166254721Semaste if (register_data.GetByteSize() != m_register_info.byte_size) 1167254721Semaste { 1168254721Semaste 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); 1169254721Semaste return; 1170254721Semaste } 1171254721Semaste 1172254721Semaste m_register_contents.reset(new DataBufferHeap(register_data.GetDataStart(), register_data.GetByteSize())); 1173254721Semaste 1174254721Semaste Error write_error; 1175254721Semaste 1176254721Semaste map.WriteMemory(load_addr, register_data.GetDataStart(), register_data.GetByteSize(), write_error); 1177254721Semaste 1178254721Semaste if (!write_error.Success()) 1179254721Semaste { 1180254721Semaste err.SetErrorStringWithFormat("couldn't write the contents of register %s: %s", m_register_info.name, write_error.AsCString()); 1181254721Semaste return; 1182254721Semaste } 1183254721Semaste } 1184254721Semaste 1185254721Semaste void Dematerialize (lldb::StackFrameSP &frame_sp, 1186254721Semaste IRMemoryMap &map, 1187254721Semaste lldb::addr_t process_address, 1188254721Semaste lldb::addr_t frame_top, 1189254721Semaste lldb::addr_t frame_bottom, 1190254721Semaste Error &err) 1191254721Semaste { 1192254721Semaste Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); 1193254721Semaste 1194254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 1195254721Semaste 1196254721Semaste if (log) 1197254721Semaste { 1198254721Semaste log->Printf("EntityRegister::Dematerialize [address = 0x%" PRIx64 ", m_register_info = %s]", 1199254721Semaste (uint64_t)load_addr, 1200254721Semaste m_register_info.name); 1201254721Semaste } 1202254721Semaste 1203254721Semaste Error extract_error; 1204254721Semaste 1205254721Semaste DataExtractor register_data; 1206254721Semaste 1207254721Semaste if (!frame_sp.get()) 1208254721Semaste { 1209254721Semaste err.SetErrorStringWithFormat("couldn't dematerialize register %s without a stack frame", m_register_info.name); 1210254721Semaste return; 1211254721Semaste } 1212254721Semaste 1213254721Semaste lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext(); 1214254721Semaste 1215254721Semaste map.GetMemoryData(register_data, load_addr, m_register_info.byte_size, extract_error); 1216254721Semaste 1217254721Semaste if (!extract_error.Success()) 1218254721Semaste { 1219254721Semaste err.SetErrorStringWithFormat("couldn't get the data for register %s: %s", m_register_info.name, extract_error.AsCString()); 1220254721Semaste return; 1221254721Semaste } 1222254721Semaste 1223254721Semaste if (!memcmp(register_data.GetDataStart(), m_register_contents->GetBytes(), register_data.GetByteSize())) 1224254721Semaste { 1225254721Semaste // No write required, and in particular we avoid errors if the register wasn't writable 1226254721Semaste 1227254721Semaste m_register_contents.reset(); 1228254721Semaste return; 1229254721Semaste } 1230254721Semaste 1231254721Semaste m_register_contents.reset(); 1232254721Semaste 1233254721Semaste RegisterValue register_value (const_cast<uint8_t*>(register_data.GetDataStart()), register_data.GetByteSize(), register_data.GetByteOrder()); 1234254721Semaste 1235254721Semaste if (!reg_context_sp->WriteRegister(&m_register_info, register_value)) 1236254721Semaste { 1237254721Semaste err.SetErrorStringWithFormat("couldn't write the value of register %s", m_register_info.name); 1238254721Semaste return; 1239254721Semaste } 1240254721Semaste } 1241254721Semaste 1242254721Semaste void DumpToLog (IRMemoryMap &map, lldb::addr_t process_address, Log *log) 1243254721Semaste { 1244254721Semaste StreamString dump_stream; 1245254721Semaste 1246254721Semaste Error err; 1247254721Semaste 1248254721Semaste const lldb::addr_t load_addr = process_address + m_offset; 1249254721Semaste 1250254721Semaste 1251254721Semaste dump_stream.Printf("0x%" PRIx64 ": EntityRegister (%s)\n", load_addr, m_register_info.name); 1252254721Semaste 1253254721Semaste { 1254254721Semaste dump_stream.Printf("Value:\n"); 1255254721Semaste 1256254721Semaste DataBufferHeap data (m_size, 0); 1257254721Semaste 1258254721Semaste map.ReadMemory(data.GetBytes(), load_addr, m_size, err); 1259254721Semaste 1260254721Semaste if (!err.Success()) 1261254721Semaste { 1262254721Semaste dump_stream.Printf(" <could not be read>\n"); 1263254721Semaste } 1264254721Semaste else 1265254721Semaste { 1266254721Semaste DataExtractor extractor (data.GetBytes(), data.GetByteSize(), map.GetByteOrder(), map.GetAddressByteSize()); 1267254721Semaste 1268254721Semaste extractor.DumpHexBytes(&dump_stream, data.GetBytes(), data.GetByteSize(), 16, load_addr); 1269254721Semaste 1270254721Semaste dump_stream.PutChar('\n'); 1271254721Semaste } 1272254721Semaste } 1273254721Semaste 1274254721Semaste log->PutCString(dump_stream.GetData()); 1275254721Semaste } 1276254721Semaste 1277254721Semaste void Wipe (IRMemoryMap &map, lldb::addr_t process_address) 1278254721Semaste { 1279254721Semaste } 1280254721Semasteprivate: 1281254721Semaste RegisterInfo m_register_info; 1282254721Semaste lldb::DataBufferSP m_register_contents; 1283254721Semaste}; 1284254721Semaste 1285254721Semasteuint32_t 1286254721SemasteMaterializer::AddRegister (const RegisterInfo ®ister_info, Error &err) 1287254721Semaste{ 1288254721Semaste EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); 1289254721Semaste iter->reset (new EntityRegister (register_info)); 1290254721Semaste uint32_t ret = AddStructMember(**iter); 1291254721Semaste (*iter)->SetOffset(ret); 1292254721Semaste return ret; 1293254721Semaste} 1294254721Semaste 1295254721SemasteMaterializer::Materializer () : 1296254721Semaste m_dematerializer_wp(), 1297254721Semaste m_result_entity(NULL), 1298254721Semaste m_current_offset(0), 1299254721Semaste m_struct_alignment(8) 1300254721Semaste{ 1301254721Semaste} 1302254721Semaste 1303254721SemasteMaterializer::~Materializer () 1304254721Semaste{ 1305254721Semaste DematerializerSP dematerializer_sp = m_dematerializer_wp.lock(); 1306254721Semaste 1307254721Semaste if (dematerializer_sp) 1308254721Semaste dematerializer_sp->Wipe(); 1309254721Semaste} 1310254721Semaste 1311254721SemasteMaterializer::DematerializerSP 1312254721SemasteMaterializer::Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &error) 1313254721Semaste{ 1314254721Semaste ExecutionContextScope *exe_scope = frame_sp.get(); 1315254721Semaste 1316254721Semaste if (!exe_scope) 1317254721Semaste exe_scope = map.GetBestExecutionContextScope(); 1318254721Semaste 1319254721Semaste DematerializerSP dematerializer_sp = m_dematerializer_wp.lock(); 1320254721Semaste 1321254721Semaste if (dematerializer_sp) 1322254721Semaste { 1323254721Semaste error.SetErrorToGenericError(); 1324254721Semaste error.SetErrorString("Couldn't materialize: already materialized"); 1325254721Semaste } 1326254721Semaste 1327254721Semaste DematerializerSP ret(new Dematerializer(*this, frame_sp, map, process_address)); 1328254721Semaste 1329254721Semaste if (!exe_scope) 1330254721Semaste { 1331254721Semaste error.SetErrorToGenericError(); 1332254721Semaste error.SetErrorString("Couldn't materialize: target doesn't exist"); 1333254721Semaste } 1334254721Semaste 1335254721Semaste for (EntityUP &entity_up : m_entities) 1336254721Semaste { 1337254721Semaste entity_up->Materialize(frame_sp, map, process_address, error); 1338254721Semaste 1339254721Semaste if (!error.Success()) 1340254721Semaste return DematerializerSP(); 1341254721Semaste } 1342254721Semaste 1343254721Semaste if (Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) 1344254721Semaste { 1345254721Semaste log->Printf("Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64 ") materialized:", frame_sp.get(), process_address); 1346254721Semaste for (EntityUP &entity_up : m_entities) 1347254721Semaste entity_up->DumpToLog(map, process_address, log); 1348254721Semaste } 1349254721Semaste 1350254721Semaste m_dematerializer_wp = ret; 1351254721Semaste 1352254721Semaste return ret; 1353254721Semaste} 1354254721Semaste 1355254721Semastevoid 1356254721SemasteMaterializer::Dematerializer::Dematerialize (Error &error, lldb::ClangExpressionVariableSP &result_sp, lldb::addr_t frame_bottom, lldb::addr_t frame_top) 1357254721Semaste{ 1358254721Semaste lldb::StackFrameSP frame_sp; 1359254721Semaste 1360254721Semaste lldb::ThreadSP thread_sp = m_thread_wp.lock(); 1361254721Semaste if (thread_sp) 1362254721Semaste frame_sp = thread_sp->GetFrameWithStackID(m_stack_id); 1363254721Semaste 1364254721Semaste ExecutionContextScope *exe_scope = m_map->GetBestExecutionContextScope(); 1365254721Semaste 1366254721Semaste if (!IsValid()) 1367254721Semaste { 1368254721Semaste error.SetErrorToGenericError(); 1369254721Semaste error.SetErrorString("Couldn't dematerialize: invalid dematerializer"); 1370254721Semaste } 1371254721Semaste 1372254721Semaste if (!exe_scope) 1373254721Semaste { 1374254721Semaste error.SetErrorToGenericError(); 1375254721Semaste error.SetErrorString("Couldn't dematerialize: target is gone"); 1376254721Semaste } 1377254721Semaste else 1378254721Semaste { 1379254721Semaste if (Log *log =lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) 1380254721Semaste { 1381254721Semaste log->Printf("Materializer::Dematerialize (frame_sp = %p, process_address = 0x%" PRIx64 ") about to dematerialize:", frame_sp.get(), m_process_address); 1382254721Semaste for (EntityUP &entity_up : m_materializer->m_entities) 1383254721Semaste entity_up->DumpToLog(*m_map, m_process_address, log); 1384254721Semaste } 1385254721Semaste 1386254721Semaste for (EntityUP &entity_up : m_materializer->m_entities) 1387254721Semaste { 1388254721Semaste if (entity_up.get() == m_materializer->m_result_entity) 1389254721Semaste { 1390254721Semaste static_cast<EntityResultVariable*>(m_materializer->m_result_entity)->Dematerialize (result_sp, frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error); 1391254721Semaste } 1392254721Semaste else 1393254721Semaste { 1394254721Semaste entity_up->Dematerialize (frame_sp, *m_map, m_process_address, frame_top, frame_bottom, error); 1395254721Semaste } 1396254721Semaste 1397254721Semaste if (!error.Success()) 1398254721Semaste break; 1399254721Semaste } 1400254721Semaste } 1401254721Semaste 1402254721Semaste Wipe(); 1403254721Semaste} 1404254721Semaste 1405254721Semastevoid 1406254721SemasteMaterializer::Dematerializer::Wipe () 1407254721Semaste{ 1408254721Semaste if (!IsValid()) 1409254721Semaste return; 1410254721Semaste 1411254721Semaste for (EntityUP &entity_up : m_materializer->m_entities) 1412254721Semaste { 1413254721Semaste entity_up->Wipe (*m_map, m_process_address); 1414254721Semaste } 1415254721Semaste 1416254721Semaste m_materializer = NULL; 1417254721Semaste m_map = NULL; 1418254721Semaste m_process_address = LLDB_INVALID_ADDRESS; 1419254721Semaste} 1420