static lldb::addr_t GetObjectPointer (lldb::StackFrameSP frame_sp, ConstString &object_name, Error &err) { err.Clear(); if (!frame_sp) { err.SetErrorStringWithFormat("Couldn't load '%s' because the context is incomplete", object_name.AsCString()); return LLDB_INVALID_ADDRESS; } lldb::VariableSP var_sp; lldb::ValueObjectSP valobj_sp; valobj_sp = frame_sp->GetValueForVariableExpressionPath(object_name.AsCString(), lldb::eNoDynamicValues, StackFrame::eExpressionPathOptionCheckPtrVsMember || StackFrame::eExpressionPathOptionsAllowDirectIVarAccess || StackFrame::eExpressionPathOptionsNoFragileObjcIvar || StackFrame::eExpressionPathOptionsNoSyntheticChildren || StackFrame::eExpressionPathOptionsNoSyntheticArrayRange, var_sp, err); if (!err.Success()) return LLDB_INVALID_ADDRESS; lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); if (ret == LLDB_INVALID_ADDRESS) { err.SetErrorStringWithFormat("Couldn't load '%s' because its value couldn't be evaluated", object_name.AsCString()); return LLDB_INVALID_ADDRESS; } return ret; }
Error ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp) { Error error; if (!new_value_sp) { error.SetErrorString("Empty value object for return value."); return error; } CompilerType clang_type = new_value_sp->GetCompilerType(); if (!clang_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 (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) { DataExtractor data; Error 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) { const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0); if (num_bytes <= 4) { uint32_t raw_value = data.GetMaxU32(&offset, num_bytes); if (reg_ctx->WriteRegisterFromUnsigned (r2_info, raw_value)) set_it_simple = true; } else { uint32_t raw_value = data.GetMaxU32(&offset, 4); if (reg_ctx->WriteRegisterFromUnsigned (r2_info, raw_value)) { const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0); uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset); if (reg_ctx->WriteRegisterFromUnsigned (r3_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 (clang_type.IsFloatingPointType (count, is_complex)) { if (is_complex) error.SetErrorString ("We don't support returning complex values at present"); else error.SetErrorString ("We don't support returning float values at present"); } if (!set_it_simple) error.SetErrorString ("We only support setting simple integer return types at present."); return error; }
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()); } } } }
Error ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp) { Error error; if (!new_value_sp) { error.SetErrorString("Empty value object for return value."); return error; } clang_type_t value_type = new_value_sp->GetClangType(); if (!value_type) { error.SetErrorString ("Null clang type for return value."); return error; } clang::ASTContext *ast_context = new_value_sp->GetClangAST(); if (!ast_context) { error.SetErrorString ("Null clang AST 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 (ClangASTContext::IsIntegerType (value_type, is_signed) || ClangASTContext::IsPointerType(value_type)) { DataExtractor data; size_t num_bytes = new_value_sp->GetData(data); uint32_t offset = 0; if (num_bytes <= 8) { const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("r0", 0); if (num_bytes <= 4) { uint32_t raw_value = data.GetMaxU32(&offset, num_bytes); if (reg_ctx->WriteRegisterFromUnsigned (r0_info, raw_value)) set_it_simple = true; } else { uint32_t raw_value = data.GetMaxU32(&offset, 4); if (reg_ctx->WriteRegisterFromUnsigned (r0_info, raw_value)) { const RegisterInfo *r1_info = reg_ctx->GetRegisterInfoByName("r1", 0); uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset); if (reg_ctx->WriteRegisterFromUnsigned (r1_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 (ClangASTContext::IsFloatingPointType (value_type, count, is_complex)) { if (is_complex) error.SetErrorString ("We don't support returning complex values at present"); else error.SetErrorString ("We don't support returning float values at present"); } if (!set_it_simple) error.SetErrorString ("We only support setting simple integer return types at present."); return error; }
Error ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp) { Error error; if (!new_value_sp) { error.SetErrorString("Empty value object for return value."); return error; } ClangASTType clang_type = new_value_sp->GetClangType(); if (!clang_type) { error.SetErrorString ("Null clang type for return value."); return error; } Thread *thread = frame_sp->GetThread().get(); RegisterContext *reg_ctx = thread->GetRegisterContext().get(); if (!reg_ctx) error.SetErrorString("no registers are available"); DataExtractor data; Error 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; } const uint32_t type_flags = clang_type.GetTypeInfo (NULL); if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) { if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer ) { lldb::offset_t offset = 0; if (num_bytes <= 16) { const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0); if (num_bytes <= 8) { uint64_t raw_value = data.GetMaxU64(&offset, num_bytes); if (!reg_ctx->WriteRegisterFromUnsigned (r2_info, raw_value)) error.SetErrorString ("failed to write register r2"); } else { uint64_t raw_value = data.GetMaxU64(&offset, 8); if (reg_ctx->WriteRegisterFromUnsigned (r2_info, raw_value)) { const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0); raw_value = data.GetMaxU64(&offset, num_bytes - offset); if (!reg_ctx->WriteRegisterFromUnsigned (r3_info, raw_value)) error.SetErrorString ("failed to write register r3"); } else error.SetErrorString ("failed to write register r2"); } } else { error.SetErrorString("We don't support returning longer than 128 bit integer values at present."); } } else if (type_flags & eTypeIsFloat) { error.SetErrorString("TODO: Handle Float Types."); } } else if (type_flags & eTypeIsVector) { error.SetErrorString("returning vector values are not supported"); } return error; }