示例#1
0
    private static void VisitLocalLoads(CodeInfo codeInfo, ClassFile.Method method, List <LocalVar> locals, Dictionary <long, LocalVar> localByStoreSite, Dictionary <int, string> storeSites, int instructionIndex, bool debug)
    {
        Debug.Assert(IsLoadLocal(method.Instructions[instructionIndex].NormalizedOpCode));
        LocalVar    local      = null;
        TypeWrapper type       = VerifierTypeWrapper.Null;
        int         localIndex = method.Instructions[instructionIndex].NormalizedArg1;
        bool        isArg      = false;

        foreach (int store in storeSites.Keys)
        {
            if (store == -1)
            {
                // it's a method argument, it has no initial store, but the type is simply the parameter type
                type  = InstructionState.FindCommonBaseType(type, codeInfo.GetLocalTypeWrapper(0, localIndex));
                isArg = true;
            }
            else
            {
                if (method.Instructions[store].NormalizedOpCode == NormalizedByteCode.__invokespecial)
                {
                    type = InstructionState.FindCommonBaseType(type, codeInfo.GetLocalTypeWrapper(store + 1, localIndex));
                }
                else if (method.Instructions[store].NormalizedOpCode == NormalizedByteCode.__static_error)
                {
                    // it's an __invokespecial that turned into a __static_error
                    // (since a __static_error doesn't continue, we don't need to set type)
                }
                else
                {
                    Debug.Assert(IsStoreLocal(method.Instructions[store].NormalizedOpCode));
                    type = InstructionState.FindCommonBaseType(type, codeInfo.GetStackTypeWrapper(store, 0));
                }
            }
            // we can't have an invalid type, because that would have failed verification earlier
            Debug.Assert(type != VerifierTypeWrapper.Invalid);

            LocalVar l;
            if (localByStoreSite.TryGetValue(MakeKey(store, localIndex), out l))
            {
                if (local == null)
                {
                    local = l;
                }
                else if (local != l)
                {
                    // If we've already defined a LocalVar and we find another one, then we merge them
                    // together.
                    // This happens for the following code fragment:
                    //
                    // int i = -1;
                    // try { i = 0; for(; ; ) System.out.println(i); } catch(Exception x) {}
                    // try { i = 0; for(; ; ) System.out.println(i); } catch(Exception x) {}
                    // System.out.println(i);
                    //
                    local = MergeLocals(locals, localByStoreSite, local, l);
                }
            }
        }
        if (local == null)
        {
            local       = new LocalVar();
            local.local = localIndex;
            if (VerifierTypeWrapper.IsThis(type))
            {
                local.type = ((VerifierTypeWrapper)type).UnderlyingType;
            }
            else
            {
                local.type = type;
            }
            local.isArg = isArg;
            if (debug)
            {
                FindLvtEntry(local, method, instructionIndex);
            }
            locals.Add(local);
        }
        else
        {
            local.isArg |= isArg;
            local.type   = InstructionState.FindCommonBaseType(local.type, type);
            Debug.Assert(local.type != VerifierTypeWrapper.Invalid);
        }
        foreach (int store in storeSites.Keys)
        {
            LocalVar v;
            if (!localByStoreSite.TryGetValue(MakeKey(store, localIndex), out v))
            {
                localByStoreSite[MakeKey(store, localIndex)] = local;
            }
            else if (v != local)
            {
                local = MergeLocals(locals, localByStoreSite, local, v);
            }
        }
    }
示例#2
0
    private static Dictionary <int, string>[] FindLocalVariablesImpl(CodeInfo codeInfo, ClassFile classFile, ClassFile.Method method, FindLocalVarState[] state)
    {
        ClassFile.Method.Instruction[] instructions = method.Instructions;
        ExceptionTableEntry[]          exceptions   = method.ExceptionTable;
        int maxLocals = method.MaxLocals;

        Dictionary <int, string>[] localStoreReaders = new Dictionary <int, string> [instructions.Length];
        bool done = false;

        while (!done)
        {
            done = true;
            for (int i = 0; i < instructions.Length; i++)
            {
                if (state[i].changed)
                {
                    done             = false;
                    state[i].changed = false;

                    FindLocalVarState curr = state[i].Copy();

                    for (int j = 0; j < exceptions.Length; j++)
                    {
                        if (exceptions[j].startIndex <= i && i < exceptions[j].endIndex)
                        {
                            state[exceptions[j].handlerIndex].Merge(curr);
                        }
                    }

                    if (IsLoadLocal(instructions[i].NormalizedOpCode) &&
                        (instructions[i].NormalizedOpCode != NormalizedByteCode.__aload || !VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(i + 1, 0))))
                    {
                        if (localStoreReaders[i] == null)
                        {
                            localStoreReaders[i] = new Dictionary <int, string>();
                        }
                        for (int j = 0; j < curr.sites[instructions[i].NormalizedArg1].Count; j++)
                        {
                            localStoreReaders[i][curr.sites[instructions[i].NormalizedArg1][j]] = "";
                        }
                    }

                    if (IsStoreLocal(instructions[i].NormalizedOpCode) &&
                        (instructions[i].NormalizedOpCode != NormalizedByteCode.__astore || !VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(i, 0))))
                    {
                        curr.Store(i, instructions[i].NormalizedArg1);
                        // if this is a store at the end of an exception block,
                        // we need to propagate the new state to the exception handler
                        for (int j = 0; j < exceptions.Length; j++)
                        {
                            if (exceptions[j].endIndex == i + 1)
                            {
                                state[exceptions[j].handlerIndex].Merge(curr);
                            }
                        }
                    }

                    if (instructions[i].NormalizedOpCode == NormalizedByteCode.__invokespecial)
                    {
                        ClassFile.ConstantPoolItemMI cpi = classFile.GetMethodref(instructions[i].Arg1);
                        if (ReferenceEquals(cpi.Name, StringConstants.INIT))
                        {
                            TypeWrapper type = codeInfo.GetRawStackTypeWrapper(i, cpi.GetArgTypes().Length);
                            // after we've invoked the constructor, the uninitialized references
                            // are now initialized
                            if (type == VerifierTypeWrapper.UninitializedThis ||
                                VerifierTypeWrapper.IsNew(type))
                            {
                                for (int j = 0; j < maxLocals; j++)
                                {
                                    if (codeInfo.GetLocalTypeWrapper(i, j) == type)
                                    {
                                        curr.Store(i, j);
                                    }
                                }
                            }
                        }
                    }
                    else if (instructions[i].NormalizedOpCode == NormalizedByteCode.__goto_finally)
                    {
                        int handler = instructions[i].HandlerIndex;

                        // Normally a store at the end of a try block doesn't affect the handler block,
                        // but in the case of a finally handler it does, so we need to make sure that
                        // we merge here in case the try block ended with a store.
                        state[handler].Merge(curr);

                        // Now we recursively analyse the handler and afterwards merge the endfault locations back to us
                        FindLocalVarState[] handlerState = new FindLocalVarState[instructions.Length];
                        handlerState[handler].Merge(curr);
                        curr = new FindLocalVarState();
                        FindLocalVariablesImpl(codeInfo, classFile, method, handlerState);

                        // Merge back to the target of our __goto_finally
                        for (int j = 0; j < handlerState.Length; j++)
                        {
                            if (instructions[j].NormalizedOpCode == NormalizedByteCode.__athrow &&
                                codeInfo.HasState(j) &&
                                VerifierTypeWrapper.IsFaultBlockException(codeInfo.GetRawStackTypeWrapper(j, 0)) &&
                                ((VerifierTypeWrapper)codeInfo.GetRawStackTypeWrapper(j, 0)).Index == handler)
                            {
                                curr.Merge(handlerState[j]);
                            }
                        }
                    }

                    switch (ByteCodeMetaData.GetFlowControl(instructions[i].NormalizedOpCode))
                    {
                    case ByteCodeFlowControl.Switch:
                    {
                        for (int j = 0; j < instructions[i].SwitchEntryCount; j++)
                        {
                            state[instructions[i].GetSwitchTargetIndex(j)].Merge(curr);
                        }
                        state[instructions[i].DefaultTarget].Merge(curr);
                        break;
                    }

                    case ByteCodeFlowControl.Branch:
                        state[instructions[i].TargetIndex].Merge(curr);
                        break;

                    case ByteCodeFlowControl.CondBranch:
                        state[instructions[i].TargetIndex].Merge(curr);
                        state[i + 1].Merge(curr);
                        break;

                    case ByteCodeFlowControl.Return:
                    case ByteCodeFlowControl.Throw:
                        break;

                    case ByteCodeFlowControl.Next:
                        state[i + 1].Merge(curr);
                        break;

                    default:
                        throw new InvalidOperationException();
                    }
                }
            }
        }
        return(localStoreReaders);
    }