static bool IsPointerValue (const CompilerType &type) { Flags type_flags(type.GetTypeInfo()); if (type_flags.AnySet(eTypeIsPointer)) return type_flags.AllClear(eTypeIsBuiltIn); return false; }
ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple (Thread &thread, CompilerType &return_clang_type) const { ValueObjectSP return_valobj_sp; Value value; if (!return_clang_type) return return_valobj_sp; value.SetCompilerType (return_clang_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return return_valobj_sp; const uint32_t type_flags = return_clang_type.GetTypeInfo (); unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB]; unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB]; // Following "IF ELSE" block categorizes various 'Fundamental Data Types'. // The terminology 'Fundamental Data Types' used here is adopted from // Table 2.1 of the reference document (specified on top of this file) if (type_flags & eTypeIsPointer) // 'Pointer' { uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff ; value.SetValueType(Value::eValueTypeScalar); value.GetScalar() = ptr; return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); } else if ((type_flags & eTypeIsScalar) || (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point' { value.SetValueType(Value::eValueTypeScalar); const size_t byte_size = return_clang_type.GetByteSize(nullptr); bool success = false; if (type_flags & eTypeIsInteger) // 'Integral' except enum { const bool is_signed = ((type_flags & eTypeIsSigned) != 0); uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff ; raw_value |= (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) & 0xffffffff) << 32; switch (byte_size) { default: break; case 16: // For clang::BuiltinType::UInt128 & Int128 // ToDo: Need to decide how to handle it break ; case 8: if (is_signed) value.GetScalar() = (int64_t)(raw_value); else value.GetScalar() = (uint64_t)(raw_value); success = true; break; case 4: if (is_signed) value.GetScalar() = (int32_t)(raw_value & UINT32_MAX); else value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX); success = true; break; case 2: if (is_signed) value.GetScalar() = (int16_t)(raw_value & UINT16_MAX); else value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX); success = true; break; case 1: if (is_signed) value.GetScalar() = (int8_t)(raw_value & UINT8_MAX); else value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX); success = true; break; } if (success) return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); } else if (type_flags & eTypeIsEnumeration) // handles enum { uint32_t enm = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff ; value.SetValueType(Value::eValueTypeScalar); value.GetScalar() = enm; return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); } else if (type_flags & eTypeIsFloat) // 'Floating Point' { if (byte_size <= 12) // handles float, double, long double, __float80 { const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("st0", 0); RegisterValue st0_value; if (reg_ctx->ReadRegister (st0_info, st0_value)) { DataExtractor data; if (st0_value.GetData(data)) { lldb::offset_t offset = 0; long double value_long_double = data.GetLongDouble(&offset); if (byte_size == 4) // float is 4 bytes { float value_float = (float)value_long_double; value.GetScalar() = value_float; success = true; } else if (byte_size == 8) // double is 8 bytes { // On Android Platform: long double is also 8 bytes // It will be handled here only. double value_double = (double)value_long_double; value.GetScalar() = value_double; success = true; } else if (byte_size == 12) // long double and __float80 are 12 bytes on i386 { value.GetScalar() = value_long_double; success = true; } } } if (success) return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); } else if(byte_size == 16) // handles __float128 { lldb::addr_t storage_addr = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff); return_valobj_sp = ValueObjectMemory::Create (&thread, "", Address (storage_addr, nullptr), return_clang_type); } } else // Neither 'Integral' nor 'Floating Point' { // If flow reaches here then check type_flags // This type_flags is unhandled } } else if (type_flags & eTypeIsComplex) // 'Complex Floating Point' { // ToDo: Yet to be implemented } else if (type_flags & eTypeIsVector) // 'Packed' { const size_t byte_size = return_clang_type.GetByteSize(nullptr); if (byte_size > 0) { const RegisterInfo *vec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0); if (vec_reg == nullptr) vec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0); if (vec_reg) { if (byte_size <= vec_reg->byte_size) { ProcessSP process_sp (thread.GetProcess()); if (process_sp) { std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0)); const ByteOrder byte_order = process_sp->GetByteOrder(); RegisterValue reg_value; if (reg_ctx->ReadRegister(vec_reg, reg_value)) { Error error; if (reg_value.GetAsMemoryData (vec_reg, heap_data_ap->GetBytes(), heap_data_ap->GetByteSize(), byte_order, error)) { DataExtractor data (DataBufferSP (heap_data_ap.release()), byte_order, process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); return_valobj_sp = ValueObjectConstResult::Create (&thread, return_clang_type, ConstString(""), data); } } } } else if (byte_size <= vec_reg->byte_size*2) { const RegisterInfo *vec_reg2 = reg_ctx->GetRegisterInfoByName("xmm1", 0); if (vec_reg2) { ProcessSP process_sp (thread.GetProcess()); if (process_sp) { std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0)); const ByteOrder byte_order = process_sp->GetByteOrder(); RegisterValue reg_value; RegisterValue reg_value2; if (reg_ctx->ReadRegister(vec_reg, reg_value) && reg_ctx->ReadRegister(vec_reg2, reg_value2)) { Error error; if (reg_value.GetAsMemoryData (vec_reg, heap_data_ap->GetBytes(), vec_reg->byte_size, byte_order, error) && reg_value2.GetAsMemoryData (vec_reg2, heap_data_ap->GetBytes() + vec_reg->byte_size, heap_data_ap->GetByteSize() - vec_reg->byte_size, byte_order, error)) { DataExtractor data (DataBufferSP (heap_data_ap.release()), byte_order, process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); return_valobj_sp = ValueObjectConstResult::Create (&thread, return_clang_type, ConstString(""), data); } } } } } } } } else // 'Decimal Floating Point' { //ToDo: Yet to be implemented } return return_valobj_sp; }
ValueObjectSP ABISysV_ppc64::GetReturnValueObjectSimple( Thread &thread, CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; Value value; if (!return_compiler_type) return return_valobj_sp; // value.SetContext (Value::eContextTypeClangType, return_value_type); value.SetCompilerType(return_compiler_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return return_valobj_sp; const uint32_t type_flags = return_compiler_type.GetTypeInfo(); if (type_flags & eTypeIsScalar) { value.SetValueType(Value::eValueTypeScalar); bool success = false; if (type_flags & eTypeIsInteger) { // Extract the register context so we can read arguments from registers const size_t byte_size = return_compiler_type.GetByteSize(nullptr); uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned( reg_ctx->GetRegisterInfoByName("r3", 0), 0); const bool is_signed = (type_flags & eTypeIsSigned) != 0; switch (byte_size) { default: break; case sizeof(uint64_t): if (is_signed) value.GetScalar() = (int64_t)(raw_value); else value.GetScalar() = (uint64_t)(raw_value); success = true; break; case sizeof(uint32_t): if (is_signed) value.GetScalar() = (int32_t)(raw_value & UINT32_MAX); else value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX); success = true; break; case sizeof(uint16_t): if (is_signed) value.GetScalar() = (int16_t)(raw_value & UINT16_MAX); else value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX); success = true; break; case sizeof(uint8_t): if (is_signed) value.GetScalar() = (int8_t)(raw_value & UINT8_MAX); else value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX); success = true; break; } } else if (type_flags & eTypeIsFloat) { if (type_flags & eTypeIsComplex) { // Don't handle complex yet. } else { const size_t byte_size = return_compiler_type.GetByteSize(nullptr); if (byte_size <= sizeof(long double)) { const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); RegisterValue f1_value; if (reg_ctx->ReadRegister(f1_info, f1_value)) { DataExtractor data; if (f1_value.GetData(data)) { lldb::offset_t offset = 0; if (byte_size == sizeof(float)) { value.GetScalar() = (float)data.GetFloat(&offset); success = true; } else if (byte_size == sizeof(double)) { value.GetScalar() = (double)data.GetDouble(&offset); success = true; } } } } } } if (success) return_valobj_sp = ValueObjectConstResult::Create( thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); } else if (type_flags & eTypeIsPointer) { unsigned r3_id = reg_ctx->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB]; value.GetScalar() = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id, 0); value.SetValueType(Value::eValueTypeScalar); return_valobj_sp = ValueObjectConstResult::Create( thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); } else if (type_flags & eTypeIsVector) { const size_t byte_size = return_compiler_type.GetByteSize(nullptr); if (byte_size > 0) { const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("v2", 0); if (altivec_reg) { if (byte_size <= altivec_reg->byte_size) { ProcessSP process_sp(thread.GetProcess()); if (process_sp) { std::unique_ptr<DataBufferHeap> heap_data_ap( new DataBufferHeap(byte_size, 0)); const ByteOrder byte_order = process_sp->GetByteOrder(); RegisterValue reg_value; if (reg_ctx->ReadRegister(altivec_reg, reg_value)) { Status error; if (reg_value.GetAsMemoryData( altivec_reg, heap_data_ap->GetBytes(), heap_data_ap->GetByteSize(), byte_order, error)) { DataExtractor data(DataBufferSP(heap_data_ap.release()), byte_order, process_sp->GetTarget() .GetArchitecture() .GetAddressByteSize()); return_valobj_sp = ValueObjectConstResult::Create( &thread, return_compiler_type, ConstString(""), data); } } } } } } } return return_valobj_sp; }
ValueObjectSP ABISysV_s390x::GetReturnValueObjectSimple( Thread &thread, CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; Value value; if (!return_compiler_type) return return_valobj_sp; // value.SetContext (Value::eContextTypeClangType, return_value_type); value.SetCompilerType(return_compiler_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return return_valobj_sp; const uint32_t type_flags = return_compiler_type.GetTypeInfo(); if (type_flags & eTypeIsScalar) { value.SetValueType(Value::eValueTypeScalar); bool success = false; if (type_flags & eTypeIsInteger) { // Extract the register context so we can read arguments from registers. llvm::Optional<uint64_t> byte_size = return_compiler_type.GetByteSize(nullptr); if (!byte_size) return return_valobj_sp; uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned( reg_ctx->GetRegisterInfoByName("r2", 0), 0); const bool is_signed = (type_flags & eTypeIsSigned) != 0; switch (*byte_size) { default: break; case sizeof(uint64_t): if (is_signed) value.GetScalar() = (int64_t)(raw_value); else value.GetScalar() = (uint64_t)(raw_value); success = true; break; case sizeof(uint32_t): if (is_signed) value.GetScalar() = (int32_t)(raw_value & UINT32_MAX); else value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX); success = true; break; case sizeof(uint16_t): if (is_signed) value.GetScalar() = (int16_t)(raw_value & UINT16_MAX); else value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX); success = true; break; case sizeof(uint8_t): if (is_signed) value.GetScalar() = (int8_t)(raw_value & UINT8_MAX); else value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX); success = true; break; } } else if (type_flags & eTypeIsFloat) { if (type_flags & eTypeIsComplex) { // Don't handle complex yet. } else { llvm::Optional<uint64_t> byte_size = return_compiler_type.GetByteSize(nullptr); if (byte_size && *byte_size <= sizeof(long double)) { const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0); RegisterValue f0_value; if (reg_ctx->ReadRegister(f0_info, f0_value)) { DataExtractor data; if (f0_value.GetData(data)) { lldb::offset_t offset = 0; if (*byte_size == sizeof(float)) { value.GetScalar() = (float)data.GetFloat(&offset); success = true; } else if (*byte_size == sizeof(double)) { value.GetScalar() = (double)data.GetDouble(&offset); success = true; } else if (*byte_size == sizeof(long double)) { // Don't handle long double yet. } } } } } } if (success) return_valobj_sp = ValueObjectConstResult::Create( thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); } else if (type_flags & eTypeIsPointer) { unsigned r2_id = reg_ctx->GetRegisterInfoByName("r2", 0)->kinds[eRegisterKindLLDB]; value.GetScalar() = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_id, 0); value.SetValueType(Value::eValueTypeScalar); return_valobj_sp = ValueObjectConstResult::Create( thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); } return return_valobj_sp; }