void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Status &err) override { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); const lldb::addr_t load_addr = process_address + m_offset; if (log) { log->Printf("EntityRegister::Materialize [address = 0x%" PRIx64 ", m_register_info = %s]", (uint64_t)load_addr, m_register_info.name); } RegisterValue reg_value; if (!frame_sp.get()) { err.SetErrorStringWithFormat( "couldn't materialize register %s without a stack frame", m_register_info.name); return; } lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext(); if (!reg_context_sp->ReadRegister(&m_register_info, reg_value)) { err.SetErrorStringWithFormat("couldn't read the value of register %s", m_register_info.name); return; } DataExtractor register_data; if (!reg_value.GetData(register_data)) { err.SetErrorStringWithFormat("couldn't get the data for register %s", m_register_info.name); return; } if (register_data.GetByteSize() != m_register_info.byte_size) { 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); return; } m_register_contents.reset(new DataBufferHeap(register_data.GetDataStart(), register_data.GetByteSize())); Status write_error; map.WriteMemory(load_addr, register_data.GetDataStart(), register_data.GetByteSize(), write_error); if (!write_error.Success()) { err.SetErrorStringWithFormat( "couldn't write the contents of register %s: %s", m_register_info.name, write_error.AsCString()); return; } }
void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, lldb::addr_t frame_top, lldb::addr_t frame_bottom, Status &err) override { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); const lldb::addr_t load_addr = process_address + m_offset; if (log) { log->Printf("EntityRegister::Dematerialize [address = 0x%" PRIx64 ", m_register_info = %s]", (uint64_t)load_addr, m_register_info.name); } Status extract_error; DataExtractor register_data; if (!frame_sp.get()) { err.SetErrorStringWithFormat( "couldn't dematerialize register %s without a stack frame", m_register_info.name); return; } lldb::RegisterContextSP reg_context_sp = frame_sp->GetRegisterContext(); map.GetMemoryData(register_data, load_addr, m_register_info.byte_size, extract_error); if (!extract_error.Success()) { err.SetErrorStringWithFormat("couldn't get the data for register %s: %s", m_register_info.name, extract_error.AsCString()); return; } if (!memcmp(register_data.GetDataStart(), m_register_contents->GetBytes(), register_data.GetByteSize())) { // No write required, and in particular we avoid errors if the register // wasn't writable m_register_contents.reset(); return; } m_register_contents.reset(); RegisterValue register_value( const_cast<uint8_t *>(register_data.GetDataStart()), register_data.GetByteSize(), register_data.GetByteOrder()); if (!reg_context_sp->WriteRegister(&m_register_info, register_value)) { err.SetErrorStringWithFormat("couldn't write the value of register %s", m_register_info.name); return; } }
Materializer::DematerializerSP Materializer::Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Status &error) { ExecutionContextScope *exe_scope = frame_sp.get(); if (!exe_scope) exe_scope = map.GetBestExecutionContextScope(); DematerializerSP dematerializer_sp = m_dematerializer_wp.lock(); if (dematerializer_sp) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't materialize: already materialized"); } DematerializerSP ret( new Dematerializer(*this, frame_sp, map, process_address)); if (!exe_scope) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't materialize: target doesn't exist"); } for (EntityUP &entity_up : m_entities) { entity_up->Materialize(frame_sp, map, process_address, error); if (!error.Success()) return DematerializerSP(); } if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) { log->Printf( "Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64 ") materialized:", static_cast<void *>(frame_sp.get()), process_address); for (EntityUP &entity_up : m_entities) entity_up->DumpToLog(map, process_address, log); } m_dematerializer_wp = ret; return ret; }
Status ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp) { Status error; if (!new_value_sp) { error.SetErrorString("Empty value object for return value."); return error; } CompilerType compiler_type = new_value_sp->GetCompilerType(); if (!compiler_type) { error.SetErrorString("Null clang type for return value."); return error; } Thread *thread = frame_sp->GetThread().get(); bool is_signed; uint32_t count; bool is_complex; RegisterContext *reg_ctx = thread->GetRegisterContext().get(); bool set_it_simple = false; if (compiler_type.IsIntegerOrEnumerationType(is_signed) || compiler_type.IsPointerType()) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3", 0); DataExtractor data; Status data_error; size_t num_bytes = new_value_sp->GetData(data, data_error); if (data_error.Fail()) { error.SetErrorStringWithFormat( "Couldn't convert return value to raw data: %s", data_error.AsCString()); return error; } lldb::offset_t offset = 0; if (num_bytes <= 8) { uint64_t raw_value = data.GetMaxU64(&offset, num_bytes); if (reg_ctx->WriteRegisterFromUnsigned(reg_info, raw_value)) set_it_simple = true; } else { error.SetErrorString("We don't support returning longer than 64 bit " "integer values at present."); } } else if (compiler_type.IsFloatingPointType(count, is_complex)) { if (is_complex) error.SetErrorString( "We don't support returning complex values at present"); else { size_t bit_width = compiler_type.GetBitSize(frame_sp.get()); if (bit_width <= 64) { DataExtractor data; Status data_error; size_t num_bytes = new_value_sp->GetData(data, data_error); if (data_error.Fail()) { error.SetErrorStringWithFormat( "Couldn't convert return value to raw data: %s", data_error.AsCString()); return error; } unsigned char buffer[16]; ByteOrder byte_order = data.GetByteOrder(); data.CopyByteOrderedData(0, num_bytes, buffer, 16, byte_order); set_it_simple = true; } else { // FIXME - don't know how to do 80 bit long doubles yet. error.SetErrorString( "We don't support returning float values > 64 bits at present"); } } } if (!set_it_simple) { // Okay we've got a structure or something that doesn't fit in a simple // register. // We should figure out where it really goes, but we don't support this yet. error.SetErrorString("We only support setting simple integer and float " "return types at present."); } return error; }
void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, lldb::addr_t frame_top, lldb::addr_t frame_bottom, Status &err) override { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); const lldb::addr_t load_addr = process_address + m_offset; if (log) { log->Printf("EntityVariable::Dematerialize [address = 0x%" PRIx64 ", m_variable_sp = %s]", (uint64_t)load_addr, m_variable_sp->GetName().AsCString()); } if (m_temporary_allocation != LLDB_INVALID_ADDRESS) { ExecutionContextScope *scope = frame_sp.get(); if (!scope) scope = map.GetBestExecutionContextScope(); lldb::ValueObjectSP valobj_sp = ValueObjectVariable::Create(scope, m_variable_sp); if (!valobj_sp) { err.SetErrorStringWithFormat( "couldn't get a value object for variable %s", m_variable_sp->GetName().AsCString()); return; } lldb_private::DataExtractor data; Status extract_error; map.GetMemoryData(data, m_temporary_allocation, valobj_sp->GetByteSize(), extract_error); if (!extract_error.Success()) { err.SetErrorStringWithFormat("couldn't get the data for variable %s", m_variable_sp->GetName().AsCString()); return; } bool actually_write = true; if (m_original_data) { if ((data.GetByteSize() == m_original_data->GetByteSize()) && !memcmp(m_original_data->GetBytes(), data.GetDataStart(), data.GetByteSize())) { actually_write = false; } } Status set_error; if (actually_write) { valobj_sp->SetData(data, set_error); if (!set_error.Success()) { err.SetErrorStringWithFormat( "couldn't write the new contents of %s back into the variable", m_variable_sp->GetName().AsCString()); return; } } Status free_error; map.Free(m_temporary_allocation, free_error); if (!free_error.Success()) { err.SetErrorStringWithFormat( "couldn't free the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), free_error.AsCString()); return; } m_original_data.reset(); m_temporary_allocation = LLDB_INVALID_ADDRESS; m_temporary_allocation_size = 0; } }
void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Status &err) override { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); const lldb::addr_t load_addr = process_address + m_offset; if (log) { log->Printf("EntityVariable::Materialize [address = 0x%" PRIx64 ", m_variable_sp = %s]", (uint64_t)load_addr, m_variable_sp->GetName().AsCString()); } ExecutionContextScope *scope = frame_sp.get(); if (!scope) scope = map.GetBestExecutionContextScope(); lldb::ValueObjectSP valobj_sp = ValueObjectVariable::Create(scope, m_variable_sp); if (!valobj_sp) { err.SetErrorStringWithFormat( "couldn't get a value object for variable %s", m_variable_sp->GetName().AsCString()); return; } Status valobj_error = valobj_sp->GetError(); if (valobj_error.Fail()) { err.SetErrorStringWithFormat("couldn't get the value of variable %s: %s", m_variable_sp->GetName().AsCString(), valobj_error.AsCString()); return; } if (m_is_reference) { DataExtractor valobj_extractor; Status extract_error; valobj_sp->GetData(valobj_extractor, extract_error); if (!extract_error.Success()) { err.SetErrorStringWithFormat( "couldn't read contents of reference variable %s: %s", m_variable_sp->GetName().AsCString(), extract_error.AsCString()); return; } lldb::offset_t offset = 0; lldb::addr_t reference_addr = valobj_extractor.GetAddress(&offset); Status write_error; map.WritePointerToMemory(load_addr, reference_addr, write_error); if (!write_error.Success()) { err.SetErrorStringWithFormat("couldn't write the contents of reference " "variable %s to memory: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString()); return; } } else { AddressType address_type = eAddressTypeInvalid; const bool scalar_is_load_address = false; lldb::addr_t addr_of_valobj = valobj_sp->GetAddressOf(scalar_is_load_address, &address_type); if (addr_of_valobj != LLDB_INVALID_ADDRESS) { Status write_error; map.WritePointerToMemory(load_addr, addr_of_valobj, write_error); if (!write_error.Success()) { err.SetErrorStringWithFormat( "couldn't write the address of variable %s to memory: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString()); return; } } else { DataExtractor data; Status extract_error; valobj_sp->GetData(data, extract_error); if (!extract_error.Success()) { err.SetErrorStringWithFormat("couldn't get the value of %s: %s", m_variable_sp->GetName().AsCString(), extract_error.AsCString()); return; } if (m_temporary_allocation != LLDB_INVALID_ADDRESS) { err.SetErrorStringWithFormat( "trying to create a temporary region for %s but one exists", m_variable_sp->GetName().AsCString()); return; } if (data.GetByteSize() < m_variable_sp->GetType()->GetByteSize()) { if (data.GetByteSize() == 0 && m_variable_sp->LocationExpression().IsValid() == false) { err.SetErrorStringWithFormat("the variable '%s' has no location, " "it may have been optimized out", m_variable_sp->GetName().AsCString()); } else { err.SetErrorStringWithFormat( "size of variable %s (%" PRIu64 ") is larger than the ValueObject's size (%" PRIu64 ")", m_variable_sp->GetName().AsCString(), m_variable_sp->GetType()->GetByteSize(), data.GetByteSize()); } return; } size_t bit_align = m_variable_sp->GetType()->GetLayoutCompilerType().GetTypeBitAlign(); size_t byte_align = (bit_align + 7) / 8; if (!byte_align) byte_align = 1; Status alloc_error; const bool zero_memory = false; m_temporary_allocation = map.Malloc( data.GetByteSize(), byte_align, lldb::ePermissionsReadable | lldb::ePermissionsWritable, IRMemoryMap::eAllocationPolicyMirror, zero_memory, alloc_error); m_temporary_allocation_size = data.GetByteSize(); m_original_data.reset( new DataBufferHeap(data.GetDataStart(), data.GetByteSize())); if (!alloc_error.Success()) { err.SetErrorStringWithFormat( "couldn't allocate a temporary region for %s: %s", m_variable_sp->GetName().AsCString(), alloc_error.AsCString()); return; } Status write_error; map.WriteMemory(m_temporary_allocation, data.GetDataStart(), data.GetByteSize(), write_error); if (!write_error.Success()) { err.SetErrorStringWithFormat( "couldn't write to the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString()); return; } Status pointer_write_error; map.WritePointerToMemory(load_addr, m_temporary_allocation, pointer_write_error); if (!pointer_write_error.Success()) { err.SetErrorStringWithFormat( "couldn't write the address of the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), pointer_write_error.AsCString()); } } } }