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