Skip to content
IRInterpreter.cpp 54.5 KiB
Newer Older
                if (!gep_inst)
                {
                    if (log)
                        log->Printf("getOpcode() returns GetElementPtr, but instruction is not a GetElementPtrInst");
                    error.SetErrorToGenericError();
                    error.SetErrorString(interpreter_internal_error);
                    return false;
                }
                
                const Value *pointer_operand = gep_inst->getPointerOperand();
                Type *pointer_type = pointer_operand->getType();
                
                lldb_private::Scalar P;
                
                if (!frame.EvaluateValue(P, pointer_operand, module))
                {
                    if (log)
                        log->Printf("Couldn't evaluate %s", PrintValue(pointer_operand).c_str());
                    error.SetErrorToGenericError();
                    error.SetErrorString(bad_value_error);
                    return false;
                }
                
                typedef SmallVector <Value *, 8> IndexVector;
                typedef IndexVector::iterator IndexIterator;
                
                SmallVector <Value *, 8> indices (gep_inst->idx_begin(),
                                                  gep_inst->idx_end());
                
                SmallVector <Value *, 8> const_indices;
                
                for (IndexIterator ii = indices.begin(), ie = indices.end();
                     ii != ie;
                     ++ii)
                {
                    ConstantInt *constant_index = dyn_cast<ConstantInt>(*ii);
                    
                    if (!constant_index)
                    {
                        lldb_private::Scalar I;
                        
                        if (!frame.EvaluateValue(I, *ii, module))
                        {
                            if (log)
                                log->Printf("Couldn't evaluate %s", PrintValue(*ii).c_str());
                            error.SetErrorToGenericError();
                            error.SetErrorString(bad_value_error);
                            return false;
                        }
                        
                        if (log)
                            log->Printf("Evaluated constant index %s as %llu", PrintValue(*ii).c_str(), I.ULongLong(LLDB_INVALID_ADDRESS));
                        
                        constant_index = cast<ConstantInt>(ConstantInt::get((*ii)->getType(), I.ULongLong(LLDB_INVALID_ADDRESS)));
                    }
                    
                    const_indices.push_back(constant_index);
                }
                
                uint64_t offset = data_layout.getIndexedOffset(pointer_type, const_indices);
                
                lldb_private::Scalar Poffset = P + offset;
                
                frame.AssignValue(inst, Poffset, module);
                
                if (log)
                {
                    log->Printf("Interpreted a GetElementPtrInst");
                    log->Printf("  P       : %s", frame.SummarizeValue(pointer_operand).c_str());
                    log->Printf("  Poffset : %s", frame.SummarizeValue(inst).c_str());
                }
            }
                break;
            case Instruction::ICmp:
            {
                const ICmpInst *icmp_inst = dyn_cast<ICmpInst>(inst);
                
                if (!icmp_inst)
                {
                    if (log)
                        log->Printf("getOpcode() returns ICmp, but instruction is not an ICmpInst");
                    error.SetErrorToGenericError();
                    error.SetErrorString(interpreter_internal_error);
                    return false;
                }
                
                CmpInst::Predicate predicate = icmp_inst->getPredicate();
                
                Value *lhs = inst->getOperand(0);
                Value *rhs = inst->getOperand(1);
                
                lldb_private::Scalar L;
                lldb_private::Scalar R;
                
                if (!frame.EvaluateValue(L, lhs, module))
                {
                    if (log)
                        log->Printf("Couldn't evaluate %s", PrintValue(lhs).c_str());
                    error.SetErrorToGenericError();
                    error.SetErrorString(bad_value_error);
                    return false;
                }
                
                if (!frame.EvaluateValue(R, rhs, module))
                {
                    if (log)
                        log->Printf("Couldn't evaluate %s", PrintValue(rhs).c_str());
                    error.SetErrorToGenericError();
                    error.SetErrorString(bad_value_error);
                    return false;
                }
                
                lldb_private::Scalar result;
                
                switch (predicate)
                {
                    default:
                        return false;
                    case CmpInst::ICMP_EQ:
                        result = (L == R);
                        break;
                    case CmpInst::ICMP_NE:
                        result = (L != R);
                        break;
                    case CmpInst::ICMP_UGT:
                        result = (L.GetRawBits64(0) > R.GetRawBits64(0));
                        break;
                    case CmpInst::ICMP_UGE:
                        result = (L.GetRawBits64(0) >= R.GetRawBits64(0));
                        break;
                    case CmpInst::ICMP_ULT:
                        result = (L.GetRawBits64(0) < R.GetRawBits64(0));
                        break;
                    case CmpInst::ICMP_ULE:
                        result = (L.GetRawBits64(0) <= R.GetRawBits64(0));
                        break;
                    case CmpInst::ICMP_SGT:
                        L.MakeSigned();
                        R.MakeSigned();
                        result = (L > R);
                        break;
                    case CmpInst::ICMP_SGE:
                        L.MakeSigned();
                        R.MakeSigned();
                        result = (L >= R);
                        break;
                    case CmpInst::ICMP_SLT:
                        L.MakeSigned();
                        R.MakeSigned();
                        result = (L < R);
                        break;
                    case CmpInst::ICMP_SLE:
                        L.MakeSigned();
                        R.MakeSigned();
                        result = (L <= R);
                        break;
                }
                
                frame.AssignValue(inst, result, module);
                
                if (log)
                {
                    log->Printf("Interpreted an ICmpInst");
                    log->Printf("  L : %s", frame.SummarizeValue(lhs).c_str());
                    log->Printf("  R : %s", frame.SummarizeValue(rhs).c_str());
                    log->Printf("  = : %s", frame.SummarizeValue(inst).c_str());
                }
            }
                break;
            case Instruction::IntToPtr:
            {
                const IntToPtrInst *int_to_ptr_inst = dyn_cast<IntToPtrInst>(inst);
                
                if (!int_to_ptr_inst)
                {
                    if (log)
                        log->Printf("getOpcode() returns IntToPtr, but instruction is not an IntToPtrInst");
                    error.SetErrorToGenericError();
                    error.SetErrorString(interpreter_internal_error);
                    return false;
                }
                
                Value *src_operand = int_to_ptr_inst->getOperand(0);
                
                lldb_private::Scalar I;
                
                if (!frame.EvaluateValue(I, src_operand, module))
                {
                    if (log)
                        log->Printf("Couldn't evaluate %s", PrintValue(src_operand).c_str());
                    error.SetErrorToGenericError();
                    error.SetErrorString(bad_value_error);
                    return false;
                }
                
                frame.AssignValue(inst, I, module);
                
                if (log)
                {
                    log->Printf("Interpreted an IntToPtr");
                    log->Printf("  Src : %s", frame.SummarizeValue(src_operand).c_str());
                    log->Printf("  =   : %s", frame.SummarizeValue(inst).c_str());
                }
            }
                break;
            case Instruction::PtrToInt:
            {
                const PtrToIntInst *ptr_to_int_inst = dyn_cast<PtrToIntInst>(inst);
                
                if (!ptr_to_int_inst)
                {
                    if (log)
                        log->Printf("getOpcode() returns PtrToInt, but instruction is not an PtrToIntInst");
                    error.SetErrorToGenericError();
                    error.SetErrorString(interpreter_internal_error);
                    return false;
                }
                
                Value *src_operand = ptr_to_int_inst->getOperand(0);
                
                lldb_private::Scalar I;
                
                if (!frame.EvaluateValue(I, src_operand, module))
                {
                    if (log)
                        log->Printf("Couldn't evaluate %s", PrintValue(src_operand).c_str());
                    error.SetErrorToGenericError();
                    error.SetErrorString(bad_value_error);
                    return false;
                }
                
                frame.AssignValue(inst, I, module);
                
                if (log)
                {
                    log->Printf("Interpreted a PtrToInt");
                    log->Printf("  Src : %s", frame.SummarizeValue(src_operand).c_str());
                    log->Printf("  =   : %s", frame.SummarizeValue(inst).c_str());
                }
            }
                break;
            case Instruction::Trunc:
            {
                const TruncInst *trunc_inst = dyn_cast<TruncInst>(inst);
                
                if (!trunc_inst)
                {
                    if (log)
                        log->Printf("getOpcode() returns Trunc, but instruction is not a TruncInst");
                    error.SetErrorToGenericError();
                    error.SetErrorString(interpreter_internal_error);
                    return false;
                }
                
                Value *src_operand = trunc_inst->getOperand(0);
                
                lldb_private::Scalar I;
                
                if (!frame.EvaluateValue(I, src_operand, module))
                {
                    if (log)
                        log->Printf("Couldn't evaluate %s", PrintValue(src_operand).c_str());
                    error.SetErrorToGenericError();
                    error.SetErrorString(bad_value_error);
                    return false;
                }
                
                frame.AssignValue(inst, I, module);
                
                if (log)
                {
                    log->Printf("Interpreted a Trunc");
                    log->Printf("  Src : %s", frame.SummarizeValue(src_operand).c_str());
                    log->Printf("  =   : %s", frame.SummarizeValue(inst).c_str());
                }
            }
                break;
            case Instruction::Load:
            {
                const LoadInst *load_inst = dyn_cast<LoadInst>(inst);
                
                if (!load_inst)
                {
                    if (log)
                        log->Printf("getOpcode() returns Load, but instruction is not a LoadInst");
                    error.SetErrorToGenericError();
                    error.SetErrorString(interpreter_internal_error);
                    return false;
                }
                
                // The semantics of Load are:
                //   Create a region D that will contain the loaded data
                //   Resolve the region P containing a pointer
                //   Dereference P to get the region R that the data should be loaded from
                //   Transfer a unit of type type(D) from R to D
                
                const Value *pointer_operand = load_inst->getPointerOperand();
                
                Type *pointer_ty = pointer_operand->getType();
                PointerType *pointer_ptr_ty = dyn_cast<PointerType>(pointer_ty);
                if (!pointer_ptr_ty)
                {
                    if (log)
                        log->Printf("getPointerOperand()->getType() is not a PointerType");
                    error.SetErrorToGenericError();
                    error.SetErrorString(interpreter_internal_error);
                    return false;
                }
                Type *target_ty = pointer_ptr_ty->getElementType();
                
                lldb::addr_t D = frame.ResolveValue(load_inst, module);
                lldb::addr_t P = frame.ResolveValue(pointer_operand, module);
                
                if (D == LLDB_INVALID_ADDRESS)
                {
                    if (log)
                        log->Printf("LoadInst's value doesn't resolve to anything");
                    error.SetErrorToGenericError();
                    error.SetErrorString(bad_value_error);
                    return false;
                }
                
                if (P == LLDB_INVALID_ADDRESS)
                {
                    if (log)
                        log->Printf("LoadInst's pointer doesn't resolve to anything");
                    error.SetErrorToGenericError();
                    error.SetErrorString(bad_value_error);
                    return false;
                }
                
                lldb::addr_t R;
                lldb_private::Error read_error;
                memory_map.ReadPointerFromMemory(&R, P, read_error);
                
                if (!read_error.Success())
                {
                    if (log)
                        log->Printf("Couldn't read the address to be loaded for a LoadInst");
                    error.SetErrorToGenericError();
                    error.SetErrorString(memory_read_error);
                    return false;
                }
                
                size_t target_size = data_layout.getTypeStoreSize(target_ty);
                lldb_private::DataBufferHeap buffer(target_size, 0);
                
                read_error.Clear();
                memory_map.ReadMemory(buffer.GetBytes(), R, buffer.GetByteSize(), read_error);
                if (!read_error.Success())
                {
                    if (log)
                        log->Printf("Couldn't read from a region on behalf of a LoadInst");
                    error.SetErrorToGenericError();
                    error.SetErrorString(memory_read_error);
                    return false;
                }
                
                lldb_private::Error write_error;
                memory_map.WriteMemory(D, buffer.GetBytes(), buffer.GetByteSize(), write_error);
                if (!write_error.Success())
                {
                    if (log)
                        log->Printf("Couldn't write to a region on behalf of a LoadInst");
                    error.SetErrorToGenericError();
                    error.SetErrorString(memory_read_error);
                    return false;
                }
                
                if (log)
                {
                    log->Printf("Interpreted a LoadInst");
Matt Kopec's avatar
Matt Kopec committed
                    log->Printf("  P : 0x%" PRIx64, P);
                    log->Printf("  R : 0x%" PRIx64, R);
                    log->Printf("  D : 0x%" PRIx64, D);
                }
            }
                break;
            case Instruction::Ret:
            {
                return true;
            }
            case Instruction::Store:
            {
                const StoreInst *store_inst = dyn_cast<StoreInst>(inst);
                
                if (!store_inst)
                {
                    if (log)
                        log->Printf("getOpcode() returns Store, but instruction is not a StoreInst");
                    error.SetErrorToGenericError();
                    error.SetErrorString(interpreter_internal_error);
                    return false;
                }
                
                // The semantics of Store are:
                //   Resolve the region D containing the data to be stored
                //   Resolve the region P containing a pointer
                //   Dereference P to get the region R that the data should be stored in
                //   Transfer a unit of type type(D) from D to R
                
                const Value *value_operand = store_inst->getValueOperand();
                const Value *pointer_operand = store_inst->getPointerOperand();
                
                Type *pointer_ty = pointer_operand->getType();
                PointerType *pointer_ptr_ty = dyn_cast<PointerType>(pointer_ty);
                if (!pointer_ptr_ty)
                    return false;
                Type *target_ty = pointer_ptr_ty->getElementType();
                
                lldb::addr_t D = frame.ResolveValue(value_operand, module);
                lldb::addr_t P = frame.ResolveValue(pointer_operand, module);
                
                if (D == LLDB_INVALID_ADDRESS)
                {
                    if (log)
                        log->Printf("StoreInst's value doesn't resolve to anything");
                    error.SetErrorToGenericError();
                    error.SetErrorString(bad_value_error);
                    return false;
                }
                
                if (P == LLDB_INVALID_ADDRESS)
                {
                    if (log)
                        log->Printf("StoreInst's pointer doesn't resolve to anything");
                    error.SetErrorToGenericError();
                    error.SetErrorString(bad_value_error);
                    return false;
                }
                
                lldb::addr_t R;
                lldb_private::Error read_error;
                memory_map.ReadPointerFromMemory(&R, P, read_error);
                
                if (!read_error.Success())
                {
                    if (log)
                        log->Printf("Couldn't read the address to be loaded for a LoadInst");
                    error.SetErrorToGenericError();
                    error.SetErrorString(memory_read_error);
                    return false;
                }
                
                size_t target_size = data_layout.getTypeStoreSize(target_ty);
                lldb_private::DataBufferHeap buffer(target_size, 0);
                
                read_error.Clear();
                memory_map.ReadMemory(buffer.GetBytes(), D, buffer.GetByteSize(), read_error);
                if (!read_error.Success())
                {
                    if (log)
                        log->Printf("Couldn't read from a region on behalf of a StoreInst");
                    error.SetErrorToGenericError();
                    error.SetErrorString(memory_read_error);
                    return false;
                }
                
                lldb_private::Error write_error;
                memory_map.WriteMemory(R, buffer.GetBytes(), buffer.GetByteSize(), write_error);
                if (!write_error.Success())
                {
                    if (log)
                        log->Printf("Couldn't write to a region on behalf of a StoreInst");
                    error.SetErrorToGenericError();
Sean Callanan's avatar
Sean Callanan committed
                    error.SetErrorString(memory_write_error);
                    return false;
                }
                
                if (log)
                {
                    log->Printf("Interpreted a StoreInst");
Matt Kopec's avatar
Matt Kopec committed
                    log->Printf("  D : 0x%" PRIx64, D);
                    log->Printf("  P : 0x%" PRIx64, P);
                    log->Printf("  R : 0x%" PRIx64, R);
                }
            }
                break;
        }
        
        ++frame.m_ii;
    }
    
    if (num_insts >= 4096)
    {
        error.SetErrorToGenericError();
        error.SetErrorString(infinite_loop_error);
        return false;
    }
    
    return false;
}