static lldb::Format
GetItemFormatForFormat (lldb::Format format,
                        ClangASTType element_type)
{
    switch (format)
    {
        case lldb::eFormatVectorOfChar:
            return lldb::eFormatChar;
            
        case lldb::eFormatVectorOfFloat32:
        case lldb::eFormatVectorOfFloat64:
            return lldb::eFormatFloat;
            
        case lldb::eFormatVectorOfSInt16:
        case lldb::eFormatVectorOfSInt32:
        case lldb::eFormatVectorOfSInt64:
        case lldb::eFormatVectorOfSInt8:
            return lldb::eFormatDecimal;
            
        case lldb::eFormatVectorOfUInt128:
        case lldb::eFormatVectorOfUInt16:
        case lldb::eFormatVectorOfUInt32:
        case lldb::eFormatVectorOfUInt64:
        case lldb::eFormatVectorOfUInt8:
            return lldb::eFormatUnsigned;
            
        case lldb::eFormatBinary:
        case lldb::eFormatComplexInteger:
        case lldb::eFormatDecimal:
        case lldb::eFormatEnum:
        case lldb::eFormatInstruction:
        case lldb::eFormatOSType:
        case lldb::eFormatVoid:
            return eFormatHex;

        case lldb::eFormatDefault:
        {
            // special case the (default, char) combination to actually display as an integer value
            // most often, you won't want to see the ASCII characters... (and if you do, eFormatChar is a keystroke away)
            bool is_char = element_type.IsCharType();
            bool is_signed = false;
            element_type.IsIntegerType(is_signed);
            return is_char ? (is_signed ? lldb::eFormatDecimal : eFormatHex) : format;
        }
            break;
            
        default:
            return format;
    }
}
static size_t
CalculateNumChildren (ClangASTType container_type,
                      ClangASTType element_type,
                      lldb_private::ExecutionContextScope *exe_scope = nullptr // does not matter here because all we trade in are basic types
                      )
{
    auto container_size = container_type.GetByteSize(exe_scope);
    auto element_size = element_type.GetByteSize(exe_scope);
    
    if (element_size)
    {
        if (container_size % element_size)
            return 0;
        return container_size / element_size;
    }
    return 0;
}
Example #3
0
ValueObjectSP
ABI::GetReturnValueObject (Thread &thread,
                          ClangASTType &ast_type) const
{
    if (!ast_type.IsValid())
        return ValueObjectSP();
        
    Value ret_value;
    ret_value.SetContext(Value::eContextTypeClangType, 
                       ast_type.GetOpaqueQualType());
    if (GetReturnValue (thread, ret_value))
    {
        return ValueObjectConstResult::Create(
                                        thread.GetStackFrameAtIndex(0).get(),
                                        ast_type.GetASTContext(),
                                        ret_value,
                                        ConstString("FunctionReturn"));

    }
    else
        return ValueObjectSP();
}
Example #4
0
SBType::SBType (const ClangASTType &type) :
    m_opaque_sp(new TypeImpl(ClangASTType(type.GetASTContext(),
                                          type.GetOpaqueQualType())))
{
}
Example #5
0
ValueObjectSP
ABI::GetReturnValueObject (Thread &thread,
                           ClangASTType &ast_type,
                           bool persistent) const
{
    if (!ast_type.IsValid())
        return ValueObjectSP();
        
    ValueObjectSP return_valobj_sp;
        
    return_valobj_sp = GetReturnValueObjectImpl(thread, ast_type);
    if (!return_valobj_sp)
        return return_valobj_sp;
    
    // Now turn this into a persistent variable.
    // FIXME: This code is duplicated from Target::EvaluateExpression, and it is used in similar form in a couple
    // of other places.  Figure out the correct Create function to do all this work.
    
    if (persistent)
    {
        ClangPersistentVariables& persistent_variables = thread.CalculateTarget()->GetPersistentVariables();
        ConstString persistent_variable_name (persistent_variables.GetNextPersistentVariableName());

        lldb::ValueObjectSP const_valobj_sp;
        
        // Check in case our value is already a constant value
        if (return_valobj_sp->GetIsConstant())
        {
            const_valobj_sp = return_valobj_sp;
            const_valobj_sp->SetName (persistent_variable_name);
        }
        else
            const_valobj_sp = return_valobj_sp->CreateConstantValue (persistent_variable_name);

        lldb::ValueObjectSP live_valobj_sp = return_valobj_sp;
        
        return_valobj_sp = const_valobj_sp;

        ClangExpressionVariableSP clang_expr_variable_sp(persistent_variables.CreatePersistentVariable(return_valobj_sp));
               
        assert (clang_expr_variable_sp.get());
        
        // Set flags and live data as appropriate

        const Value &result_value = live_valobj_sp->GetValue();
        
        switch (result_value.GetValueType())
        {
        case Value::eValueTypeHostAddress:
        case Value::eValueTypeFileAddress:
            // we don't do anything with these for now
            break;
        case Value::eValueTypeScalar:
        case Value::eValueTypeVector:
            clang_expr_variable_sp->m_flags |= ClangExpressionVariable::EVIsFreezeDried;
            clang_expr_variable_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
            clang_expr_variable_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
            break;
        case Value::eValueTypeLoadAddress:
            clang_expr_variable_sp->m_live_sp = live_valobj_sp;
            clang_expr_variable_sp->m_flags |= ClangExpressionVariable::EVIsProgramReference;
            break;
        }
        
        return_valobj_sp = clang_expr_variable_sp->GetValueObject();
    }
    return return_valobj_sp;
}
Example #6
0
static void
PrivateAutoComplete (StackFrame *frame,
                     const std::string &partial_path,
                     const std::string &prefix_path, // Anything that has been resolved already will be in here
                     const ClangASTType& clang_type,
                     StringList &matches,
                     bool &word_complete)
{
//    printf ("\nPrivateAutoComplete()\n\tprefix_path = '%s'\n\tpartial_path = '%s'\n", prefix_path.c_str(), partial_path.c_str());
    std::string remaining_partial_path;

    const lldb::TypeClass type_class = clang_type.GetTypeClass();
    if (partial_path.empty())
    {
        if (clang_type.IsValid())
        {
            switch (type_class)
            {
                default:
                case eTypeClassArray:
                case eTypeClassBlockPointer:
                case eTypeClassBuiltin:
                case eTypeClassComplexFloat:
                case eTypeClassComplexInteger:
                case eTypeClassEnumeration:
                case eTypeClassFunction:
                case eTypeClassMemberPointer:
                case eTypeClassReference:
                case eTypeClassTypedef:
                case eTypeClassVector:
                    {
                        matches.AppendString (prefix_path);
                        word_complete = matches.GetSize() == 1;
                    }
                    break;
                    
                case eTypeClassClass:
                case eTypeClassStruct:
                case eTypeClassUnion:
                    if (prefix_path.back() != '.')
                        matches.AppendString (prefix_path + '.');
                    break;

                case eTypeClassObjCObject:
                case eTypeClassObjCInterface:
                    break;
                case eTypeClassObjCObjectPointer:
                case eTypeClassPointer:
                    {
                        bool omit_empty_base_classes = true;
                        if (clang_type.GetNumChildren (omit_empty_base_classes) > 0)
                            matches.AppendString (prefix_path + "->");
                        else
                        {
                            matches.AppendString (prefix_path);
                            word_complete = true;
                        }
                    }
                    break;
            }
        }
        else
        {
            if (frame)
            {
                const bool get_file_globals = true;
                
                VariableList *variable_list = frame->GetVariableList(get_file_globals);
                
                if (variable_list)
                {
                    const size_t num_variables = variable_list->GetSize();
                    for (size_t i=0; i<num_variables; ++i)
                    {
                        Variable *variable = variable_list->GetVariableAtIndex(i).get();
                        matches.AppendString (variable->GetName().AsCString());
                    }
                }
            }
        }
    }
    else
    {
        const char ch = partial_path[0];
        switch (ch)
        {
        case '*':
            if (prefix_path.empty())
            {
                PrivateAutoComplete (frame,
                                     partial_path.substr(1),
                                     std::string("*"),
                                     clang_type,
                                     matches,
                                     word_complete);
            }
            break;

        case '&':
            if (prefix_path.empty())
            {
                PrivateAutoComplete (frame,
                                     partial_path.substr(1),
                                     std::string("&"),
                                     clang_type,
                                     matches,
                                     word_complete);
            }
            break;

        case '-':
            if (partial_path[1] == '>' && !prefix_path.empty())
            {
                switch (type_class)
                {
                    case lldb::eTypeClassPointer:
                        {
                            ClangASTType pointee_type(clang_type.GetPointeeType());
                            if (partial_path[2])
                            {
                                // If there is more after the "->", then search deeper
                                PrivateAutoComplete (frame,
                                                     partial_path.substr(2),
                                                     prefix_path + "->",
                                                     pointee_type.GetCanonicalType(),
                                                     matches,
                                                     word_complete);
                            }
                            else
                            {
                                // Nothing after the "->", so list all members
                                PrivateAutoCompleteMembers (frame,
                                                            std::string(),
                                                            std::string(),
                                                            prefix_path + "->",
                                                            pointee_type.GetCanonicalType(),
                                                            matches,
                                                            word_complete);                            
                            }
                        }
                    default:
                        break;
                }
            }
            break;
            
        case '.':
            if (clang_type.IsValid())
            {
                switch (type_class)
                {
                    case lldb::eTypeClassUnion:
                    case lldb::eTypeClassStruct:
                    case lldb::eTypeClassClass:
                        if (partial_path[1])
                        {
                            // If there is more after the ".", then search deeper
                            PrivateAutoComplete (frame,
                                                 partial_path.substr(1),
                                                 prefix_path + ".",
                                                 clang_type,
                                                 matches,
                                                 word_complete);
                            
                        }
                        else
                        {
                            // Nothing after the ".", so list all members
                            PrivateAutoCompleteMembers (frame,
                                                        std::string(),
                                                        partial_path,
                                                        prefix_path + ".",
                                                        clang_type,
                                                        matches,
                                                        word_complete);
                        }
                    default:
                        break;
                }
            }
            break;
        default:
            if (isalpha(ch) || ch == '_' || ch == '$')
            {
                const size_t partial_path_len = partial_path.size();
                size_t pos = 1;
                while (pos < partial_path_len)
                {
                    const char curr_ch = partial_path[pos];
                    if (isalnum(curr_ch) || curr_ch == '_'  || curr_ch == '$')
                    {
                        ++pos;
                        continue;
                    }
                    break;
                }

                std::string token(partial_path, 0, pos);
                remaining_partial_path = partial_path.substr(pos);
                
                if (clang_type.IsValid())
                {
                    PrivateAutoCompleteMembers (frame,
                                                token,
                                                remaining_partial_path,
                                                prefix_path,
                                                clang_type,
                                                matches,
                                                word_complete);
                }
                else if (frame)
                {
                    // We haven't found our variable yet
                    const bool get_file_globals = true;
                    
                    VariableList *variable_list = frame->GetVariableList(get_file_globals);
                    
                    if (!variable_list)
                        break;
                    
                    const size_t num_variables = variable_list->GetSize();
                    for (size_t i=0; i<num_variables; ++i)
                    {
                        Variable *variable = variable_list->GetVariableAtIndex(i).get();
                        
                        if (!variable)
                            continue;
                        
                        const char *variable_name = variable->GetName().AsCString();
                        if (strstr(variable_name, token.c_str()) == variable_name)
                        {
                            if (strcmp (variable_name, token.c_str()) == 0)
                            {
                                Type *variable_type = variable->GetType();
                                if (variable_type)
                                {
                                    ClangASTType variable_clang_type (variable_type->GetClangForwardType());
                                    PrivateAutoComplete (frame,
                                                         remaining_partial_path,
                                                         prefix_path + token, // Anything that has been resolved already will be in here
                                                         variable_clang_type.GetCanonicalType(),
                                                         matches,
                                                         word_complete);
                                }
                                else
                                {
                                    matches.AppendString (prefix_path + variable_name);
                                }
                            }
                            else if (remaining_partial_path.empty())
                            {
                                matches.AppendString (prefix_path + variable_name);
                            }
                        }
                    }
                }
            }
            break;
        }
    }
}
Example #7
0
static void
PrivateAutoCompleteMembers (StackFrame *frame,
                            const std::string &partial_member_name,
                            const std::string &partial_path,
                            const std::string &prefix_path, // Anything that has been resolved already will be in here
                            const ClangASTType& clang_type,
                            StringList &matches,
                            bool &word_complete)
{

    // We are in a type parsing child members
    const uint32_t num_bases = clang_type.GetNumDirectBaseClasses();
    
    if (num_bases > 0)
    {
        for (uint32_t i = 0; i < num_bases; ++i)
        {
            ClangASTType base_class_type (clang_type.GetDirectBaseClassAtIndex (i, nullptr));
            
            PrivateAutoCompleteMembers (frame,
                                        partial_member_name,
                                        partial_path,
                                        prefix_path,
                                        base_class_type.GetCanonicalType(),
                                        matches,
                                        word_complete);
        }
    }

    const uint32_t num_vbases = clang_type.GetNumVirtualBaseClasses();
    
    if (num_vbases > 0)
    {
        for (uint32_t i = 0; i < num_vbases; ++i)
        {
            ClangASTType vbase_class_type (clang_type.GetVirtualBaseClassAtIndex(i,nullptr));
            
            PrivateAutoCompleteMembers (frame,
                                        partial_member_name,
                                        partial_path,
                                        prefix_path,
                                        vbase_class_type.GetCanonicalType(),
                                        matches,
                                        word_complete);
        }
    }

    // We are in a type parsing child members
    const uint32_t num_fields = clang_type.GetNumFields();
    
    if (num_fields > 0)
    {
        for (uint32_t i = 0; i < num_fields; ++i)
        {
            std::string member_name;
            
            ClangASTType member_clang_type = clang_type.GetFieldAtIndex (i, member_name, nullptr, nullptr, nullptr);
            
            if (partial_member_name.empty() ||
                member_name.find(partial_member_name) == 0)
            {
                if (member_name == partial_member_name)
                {
                    PrivateAutoComplete (frame,
                                         partial_path,
                                         prefix_path + member_name, // Anything that has been resolved already will be in here
                                         member_clang_type.GetCanonicalType(),
                                         matches,
                                         word_complete);
                }
                else
                {
                    matches.AppendString (prefix_path + member_name);
                }
            }
        }
    }
}
Example #8
0
ValueObjectSP
ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
{
    ValueObjectSP return_valobj_sp;

    if (!return_clang_type)
        return return_valobj_sp;

    ExecutionContext exe_ctx (thread.shared_from_this());
    return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type);
    if (return_valobj_sp)
        return return_valobj_sp;

    RegisterContextSP reg_ctx_sp = thread.GetRegisterContext();
    if (!reg_ctx_sp)
        return return_valobj_sp;

    const size_t bit_width = return_clang_type.GetBitSize(&thread);
    if (return_clang_type.IsAggregateType())
    {
        Target *target = exe_ctx.GetTargetPtr();
        bool is_memory = true;
        if (bit_width <= 128)
        {
            ByteOrder target_byte_order = target->GetArchitecture().GetByteOrder();
            DataBufferSP data_sp (new DataBufferHeap(16, 0));
            DataExtractor return_ext (data_sp,
                                      target_byte_order,
                                      target->GetArchitecture().GetAddressByteSize());

            const RegisterInfo *r3_info = reg_ctx_sp->GetRegisterInfoByName("r3", 0);
            const RegisterInfo *rdx_info = reg_ctx_sp->GetRegisterInfoByName("rdx", 0);

            RegisterValue r3_value, rdx_value;
            reg_ctx_sp->ReadRegister (r3_info, r3_value);
            reg_ctx_sp->ReadRegister (rdx_info, rdx_value);

            DataExtractor r3_data, rdx_data;

            r3_value.GetData(r3_data);
            rdx_value.GetData(rdx_data);

            uint32_t fp_bytes = 0;       // Tracks how much of the xmm registers we've consumed so far
            uint32_t integer_bytes = 0;  // Tracks how much of the r3/rds registers we've consumed so far

            const uint32_t num_children = return_clang_type.GetNumFields ();

            // Since we are in the small struct regime, assume we are not in memory.
            is_memory = false;

            for (uint32_t idx = 0; idx < num_children; idx++)
            {
                std::string name;
                uint64_t field_bit_offset = 0;
                bool is_signed;
                bool is_complex;
                uint32_t count;

                ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
                const size_t field_bit_width = field_clang_type.GetBitSize(&thread);

                // If there are any unaligned fields, this is stored in memory.
                if (field_bit_offset % field_bit_width != 0)
                {
                    is_memory = true;
                    break;
                }

                uint32_t field_byte_width = field_bit_width/8;
                uint32_t field_byte_offset = field_bit_offset/8;


                DataExtractor *copy_from_extractor = NULL;
                uint32_t       copy_from_offset    = 0;

                if (field_clang_type.IsIntegerType (is_signed) || field_clang_type.IsPointerType ())
                {
                    if (integer_bytes < 8)
                    {
                        if (integer_bytes + field_byte_width <= 8)
                        {
                            // This is in RAX, copy from register to our result structure:
                            copy_from_extractor = &r3_data;
                            copy_from_offset = integer_bytes;
                            integer_bytes += field_byte_width;
                        }
                        else
                        {
                            // The next field wouldn't fit in the remaining space, so we pushed it to rdx.
                            copy_from_extractor = &rdx_data;
                            copy_from_offset = 0;
                            integer_bytes = 8 + field_byte_width;

                        }
                    }
                    else if (integer_bytes + field_byte_width <= 16)
                    {
                        copy_from_extractor = &rdx_data;
                        copy_from_offset = integer_bytes - 8;
                        integer_bytes += field_byte_width;
                    }
                    else
                    {
                        // The last field didn't fit.  I can't see how that would happen w/o the overall size being
                        // greater than 16 bytes.  For now, return a NULL return value object.
                        return return_valobj_sp;
                    }
                }
                else if (field_clang_type.IsFloatingPointType (count, is_complex))
                {
                    // Structs with long doubles are always passed in memory.
                    if (field_bit_width == 128)
                    {
                        is_memory = true;
                        break;
                    }
                    else if (field_bit_width == 64)
                    {
                        copy_from_offset = 0;
                        fp_bytes += field_byte_width;
                    }
                    else if (field_bit_width == 32)
                    {
                        // This one is kind of complicated.  If we are in an "eightbyte" with another float, we'll
                        // be stuffed into an xmm register with it.  If we are in an "eightbyte" with one or more ints,
                        // then we will be stuffed into the appropriate GPR with them.
                        bool in_gpr;
                        if (field_byte_offset % 8 == 0)
                        {
                            // We are at the beginning of one of the eightbytes, so check the next element (if any)
                            if (idx == num_children - 1)
                                in_gpr = false;
                            else
                            {
                                uint64_t next_field_bit_offset = 0;
                                ClangASTType next_field_clang_type = return_clang_type.GetFieldAtIndex (idx + 1,
                                                                                                        name,
                                                                                                        &next_field_bit_offset,
                                                                                                        NULL,
                                                                                                        NULL);
                                if (next_field_clang_type.IsIntegerType (is_signed))
                                    in_gpr = true;
                                else
                                {
                                    copy_from_offset = 0;
                                    in_gpr = false;
                                }
                            }

                        }
                        else if (field_byte_offset % 4 == 0)
                        {
                            // We are inside of an eightbyte, so see if the field before us is floating point:
                            // This could happen if somebody put padding in the structure.
                            if (idx == 0)
                                in_gpr = false;
                            else
                            {
                                uint64_t prev_field_bit_offset = 0;
                                ClangASTType prev_field_clang_type = return_clang_type.GetFieldAtIndex (idx - 1,
                                                                                                        name,
                                                                                                        &prev_field_bit_offset,
                                                                                                        NULL,
                                                                                                        NULL);
                                if (prev_field_clang_type.IsIntegerType (is_signed))
                                    in_gpr = true;
                                else
                                {
                                    copy_from_offset = 4;
                                    in_gpr = false;
                                }
                            }

                        }
                        else
                        {
                            is_memory = true;
                            continue;
                        }

                        // Okay, we've figured out whether we are in GPR or XMM, now figure out which one.
                        if (in_gpr)
                        {
                            if (integer_bytes < 8)
                            {
                                // This is in RAX, copy from register to our result structure:
                                copy_from_extractor = &r3_data;
                                copy_from_offset = integer_bytes;
                                integer_bytes += field_byte_width;
                            }
                            else
                            {
                                copy_from_extractor = &rdx_data;
                                copy_from_offset = integer_bytes - 8;
                                integer_bytes += field_byte_width;
                            }
                        }
                        else
                        {
                            fp_bytes += field_byte_width;
                        }
                    }
                }

                // These two tests are just sanity checks.  If I somehow get the
                // type calculation wrong above it is better to just return nothing
                // than to assert or crash.
                if (!copy_from_extractor)
                    return return_valobj_sp;
                if (copy_from_offset + field_byte_width > copy_from_extractor->GetByteSize())
                    return return_valobj_sp;

                copy_from_extractor->CopyByteOrderedData (copy_from_offset,
                                                          field_byte_width,
                                                          data_sp->GetBytes() + field_byte_offset,
                                                          field_byte_width,
                                                          target_byte_order);
            }

            if (!is_memory)
            {
                // The result is in our data buffer.  Let's make a variable object out of it:
                return_valobj_sp = ValueObjectConstResult::Create (&thread,
                                                                   return_clang_type,
                                                                   ConstString(""),
                                                                   return_ext);
            }
        }


        // FIXME: This is just taking a guess, r3 may very well no longer hold the return storage location.
        // If we are going to do this right, when we make a new frame we should check to see if it uses a memory
        // return, and if we are at the first instruction and if so stash away the return location.  Then we would
        // only return the memory return value if we know it is valid.

        if (is_memory)
        {
            unsigned r3_id = reg_ctx_sp->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB];
            lldb::addr_t storage_addr = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id, 0);
            return_valobj_sp = ValueObjectMemory::Create (&thread,
                                                          "",
                                                          Address (storage_addr, NULL),
                                                          return_clang_type);
        }
    }

    return return_valobj_sp;
}
Example #9
0
ValueObjectSP
ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread,
                                            ClangASTType &return_clang_type) const
{
    ValueObjectSP return_valobj_sp;
    Value value;

    if (!return_clang_type)
        return return_valobj_sp;

    //value.SetContext (Value::eContextTypeClangType, return_value_type);
    value.SetClangType (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 ();
    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_clang_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_clang_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_clang_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))
                        {
                            Error 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_clang_type,
                                                                                   ConstString(""),
                                                                                   data);
                            }
                        }
                    }
                }
            }
        }
    }

    return return_valobj_sp;
}
Example #10
0
ValueObjectSP
ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
{
    ValueObjectSP return_valobj_sp;
    Value value;

    ExecutionContext exe_ctx (thread.shared_from_this());
    if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL)
        return return_valobj_sp;

    value.SetClangType(return_clang_type);

    RegisterContext *reg_ctx = thread.GetRegisterContext().get();
    if (!reg_ctx)
        return return_valobj_sp;

    const size_t byte_size = return_clang_type.GetByteSize(nullptr);
    const uint32_t type_flags = return_clang_type.GetTypeInfo (NULL);

    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
            // In MIPS register "r2" (v0) holds the integer function return values

            uint64_t raw_value = reg_ctx->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;
            }
        }

        if (success)
        return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
                                                           value,
                                                           ConstString(""));
    }
    else if (type_flags & eTypeIsPointer)
    {
        value.SetValueType(Value::eValueTypeScalar);
        uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0);
        value.GetScalar() = (uint64_t)(raw_value);

        return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
                                                           value,
                                                           ConstString(""));
    }
    else if (type_flags & eTypeIsVector)
    {
        // TODO: Handle vector types
    }
    return return_valobj_sp;
}