コード例 #1
0
        public static void SmallSnippet(int a, double b)
        {
            if (b < (a + 15))
            {
                var s = ((b / a).ToString() + "str").ToString();
                checked
                {
                    var x = a + 10;

                    switch (x)
                    {
                    case 2:
                        var y = (UInt32)4 + (UInt32)x;
                        Log.WriteLine(String.Empty + x + y);
                        break;

                    case 4:
                        a = 15;
                        var arr = new Type[1];
                        arr[0] = typeof(Single);
                        break;

                    case 7:
                        Object abox = a;
                        b = (Int32)(UInt32)abox + 5;
                        var c = (UInt32)b < 2;
                        break;

                    default:
                        var z = typeof(Type);
                        Log.WriteLine(z.ToString() + sizeof(Double));
                        throw new NotSupportedException();
                    }
                }
            }
            else
            {
                DateTime dt1;
                dt1 = DateTime.Now;
                var dt  = new DateTime(1987, 8, 5);
                var arr = new[] { dt, new DateTime(dt1.Year, dt1.Month, dt1.Day) };
                (arr.Length == new List <Int32>().Count).AssertTrue();

                Func <int, int> foo = i => dt.Day + i + arr[15].Month;
                (foo(arr.Length) != 5.0d).AssertTrue();
                arr[4] = dt;

                var dts = new List <DateTime>();
                var ss  = dts[0].ToString();

                IILOp iilop = null;
                (iilop is ILOp && new [] { "hello", "world" }[0] == "hello").AssertFalse();
            }
        }
コード例 #2
0
ファイル: ILTrait.cs プロジェクト: xeno-by/truesight-lite
        public static ILGenerator clone(this ILGenerator il, IILOp op)
        {
            // todo #1. also take into account that we need to update stacksize
            // todo #2. what is RecordTokenFixup()?

            // load some internals
            var methodBuilder = il.Get("m_methodBuilder").AssertCast<MethodBuilder>();
            var typeBuilder = methodBuilder.Get("m_containingType").AssertCast<TypeBuilder>();
            var ilModule = typeBuilder.Get("m_module").AssertCast<ModuleBuilder>();

            // if op has some prefixes, clone them first
            op.Prefixes.ForEach(prefix => il.clone(prefix));

            // hello, Shlemiel the Painter...
            var operand = op.BytesOfOperand.ToArray();

            // fixup metadata tokens
            // 1. if op doesn't have a module specified, we just crash
            // 2. if op references a module builder, we verify that ilgen references it too
            //    since as of .NET 3.5 you cannot resolve a token in module builder
            // 3. if op has a regular module, we proceed to fixup
            var opModule = op.Get("Module").AssertCast<Module>();
            opModule.AssertNotNull();

            if (opModule is ModuleBuilder)
            {
                (opModule == ilModule).AssertTrue();
            }
            else
            {
                int newToken;

                // prepare to process ldtokens
                var ldc = op as Ldc;
                var ldc_value = ldc == null ? null : ldc.Value;
                var ldc_member = null as MemberInfo;
                if (ldc_value != null)
                {
                    if (ldc_value is RuntimeTypeHandle)
                    {
                        var rth = (RuntimeTypeHandle)ldc_value;
                        ldc_member = Type.GetTypeFromHandle(rth);
                    }
                    else if (ldc_value is RuntimeMethodHandle)
                    {
                        var rmh = (RuntimeMethodHandle)ldc_value;
                        ldc_member = MethodBase.GetMethodFromHandle(rmh);
                    }
                    else if (ldc_value is RuntimeFieldHandle)
                    {
                        var rfh = (RuntimeFieldHandle)ldc_value;
                        ldc_member = FieldInfo.GetFieldFromHandle(rfh);
                    }
                }

                // process special case - ldtoken
                var operandType = op.OpSpec.OperandType;
                if (operandType == OperandType.InlineTok)
                {
                    ldc_member.AssertNotNull();
                    if (ldc_member is Type)
                    {
                        operandType = OperandType.InlineType;
                    }
                    else if (ldc_member is MethodBase)
                    {
                        operandType = OperandType.InlineMethod;
                    }
                    else if (ldc_member is FieldInfo)
                    {
                        operandType = OperandType.InlineField;
                    }
                    else
                    {
                        throw AssertionHelper.Fail();
                    }
                }

                // process all other cases
                switch (operandType)
                {
                    case OperandType.InlineType:
                        var type = (ldc_member ?? op.GetOrDefault("Type") ?? op.GetOrDefault("Resolved")).AssertCast<Type>();
                        if (op.OpSpec.OpCode == OpCodes.Newarr) type = type.GetElementType();
                        newToken = ilModule.GetTypeToken(type).Token;
                        operand = BitConverter.GetBytes(newToken);
                        break;

                    case OperandType.InlineField:
                        var field = (ldc_member ?? op.GetOrDefault("Field") ?? op.GetOrDefault("Resolved")).AssertCast<FieldInfo>();
                        newToken = ilModule.GetFieldToken(field).Token;
                        operand = BitConverter.GetBytes(newToken);
                        break;

                    case OperandType.InlineMethod:
                        // note 1. Module::GetMethodToken won't work here 
                        // since it returns index of an entry in the MemberRef metadata table (0x0a)
                        // closed generic methods are stored a separate metadata table (MethodSpec, 0x2b)

                        var method = (ldc_member ?? op.GetOrDefault("Method") ?? op.GetOrDefault("Ctor") ?? op.GetOrDefault("Resolved")).AssertCast<MethodBase>();
                        var getMethodToken = typeof(ILGenerator).GetMethod("GetMethodToken", BF.PrivateInstance);
                        newToken = (int)getMethodToken.Invoke(il, new Object[] { method, null, false });
                        operand = BitConverter.GetBytes(newToken);
                        break;

                    case OperandType.InlineString:
                        var @string = (op.GetOrDefault("Value") ?? op.GetOrDefault("Resolved")).AssertCast<String>();
                        newToken = ilModule.GetStringConstant(@string).Token;
                        operand = BitConverter.GetBytes(newToken);
                        break;

                    case OperandType.InlineSig:
                        // todo. implement this
                        throw AssertionHelper.Fail();

                    case OperandType.InlineBrTarget:
                    case OperandType.InlineI:
                    case OperandType.InlineI8:
                    case OperandType.InlineNone:
#pragma warning disable 612, 618
                    case OperandType.InlinePhi:
#pragma warning restore 612, 618
                    case OperandType.InlineR:
                    case OperandType.InlineSwitch:
                    case OperandType.InlineVar:
                    case OperandType.ShortInlineBrTarget:
                    case OperandType.ShortInlineI:
                    case OperandType.ShortInlineR:
                    case OperandType.ShortInlineVar:
                        // do nothing - operand ain't needs a fixup
                        break;

                    default:
                        throw AssertionHelper.Fail();
                }
            }

            // write the op to the output stream
            return il.raw(op.OpSpec.OpCode, operand);
        }
コード例 #3
0
ファイル: ILTrait.cs プロジェクト: xeno-by/truesight-lite
 public static ILGenerator EmitClone(this ILGenerator il, IILOp op)
 {
     return il.clone(op);
 }
コード例 #4
0
ファイル: ILRewriter.cs プロジェクト: xeno-by/truesight-lite
        public void DoRewrite()
        {
            _status.InProgress.AssertTrue();

            using (_status)
            {
                Func<byte[]> m_ILStream = () => _il.Get("m_ILStream").AssertCast<byte[]>();
                var typeBuilder = _dest.Get("m_containingType").AssertCast<TypeBuilder>();
                var module = typeBuilder.Get("m_module").AssertCast<ModuleBuilder>();
                Func<int> get_length = () => _il.Get("m_length").AssertCast<int>();
                Action<int> set_length = v => _il.Set("m_length", v);

                // Stage 1: Write rewritten ops according to _logic
                // So far we don't care about branches being fix't up
                var rawIl_BeforeStage1 = _src.ParseBody().RawIL;
                TraceRawIl(rawIl_BeforeStage1, 0);

                foreach (var op in _body)
                {
                    _curr = op;
                    _logic(op, this);
                }

                // Stage 2: Replace short branches with regular ones
                // since fixups (see below) might overflow the 1-byte offset storage
                _rewrittenIL = m_ILStream().Take(get_length()).ToArray();
                TraceRawIl(_rewrittenIL, 1);
                set_length(0);

                var fixupUpdates = new List<Action>();
                var branchExpansionPoints = new Dictionary<int, int>();
                foreach (var rop in _rewrittenIL.ParseRawIL(module))
                {
                    var rop1 = rop;
                    if (rop1 is Branch)
                    {
                        var br = rop1.AssertCast<Branch>();
                        if (rop1.OpSpec.OperandType == OperandType.ShortInlineBrTarget)
                        {
                            // rewrite short branch to normal form
                            var opcode_sig = rop1.OpSpec.OpCode.Value + 0x0d;
                            var allOpcodes = typeof(OpCodes).GetFields(BF.PublicStatic).Select(f => f.GetValue(null).AssertCast<OpCode>());
                            var opcode = allOpcodes.Single(oc => oc.Value == opcode_sig);
                            _il.raw(opcode, BitConverter.GetBytes(br.RelativeTargetOffset));

                            // update fixup of the next operation
                            // fixup = translate from original offsets to after-stage-2 ones
                            var preImage = _off2op[RewrittenToNearestOrig(rop1.Offset)];
                            if (preImage.Next != null) fixupUpdates.Add(() => _fixups[preImage.Next] += 3);

                            // update the map that memorizes BEPs in after-stage-1 coordinates
                            fixupUpdates.Add(() => branchExpansionPoints[rop1.Offset] = 3);

                            // also be careful to fixup _offsetsModeChangeLog => lazily!
                            // fixup = translate from after-stage-1 to after-stage-2 coordinates
                            foreach (var entry in _offsetsModeChangeLog)
                            {
                                (rop1.Offset < entry.Offset && entry.Offset < rop1.OffsetOfNextOp).AssertFalse();

                                var entry1 = entry;
                                var fixup = rop1.Offset >= entry1.Offset ? 0 : 3;
                                fixupUpdates.Add(() => entry1.Offset += fixup);
                            }
                        }
                        else
                        {
                            _il.clone(rop1);
                        }
                    }
                    else
                    {
                        _il.clone(rop1);
                    }
                }

                // we defer updates so that they won't f**k up _fixups in process
                fixupUpdates.RunEach();

                // Stage 3: Fixup branches since their offsets are most likely invalid now
                // todo. also fixup switches and protected regions
                //
                // note. this works as follows:
                // 1) if an instruction was emitted during OffsetsMode.Original, 
                //    i.e. (if EnterXXXMode wasn't called) during Clone 
                //    it needs a fixup and uses the main fixup log, i.e. _fixups.
                // 2) if an instruction was emitted during OffsetsMode.Rewritten,
                //    i.e. (if EnterXXXMode wasn't called) during Clone 
                //    it ain't need a fixup due to rewriting, 
                //    but does need a fixup to compensate for short branches expansion (see above)
                //    and thusly uses the branchExpansionFixups log
                _rewrittenIL = m_ILStream().Take(get_length()).ToArray();
                TraceRawIl(_rewrittenIL, 2);
                foreach (var rop in _rewrittenIL.ParseRawIL(module))
                {
                    // note #1.
                    // we can't use Target here since offsets are most likely broken at the moment
                    // at best it'll return null, and at worst it'll crash

                    // note #2.
                    // we can't use AbsoluteTargetOffset either since it positions at after-stage-2 IL
                    // but not to before-stage-1 IL (i.e. original)

                    // note #3.
                    // neither we can use RewrittenToOrig(rop.Offset) 
                    // since, even if we're at OffsetsMode.Original, the rop might've been issued during r/w

                    if (rop is Branch)
                    {
                        var br = rop.AssertCast<Branch>();
                        var pivot = br.OffsetOfNextOp;

                        Action<int> rewriteRelOffset = newRelOffset =>
                        {
                            var addrOfOperand = rop.OffsetOfOperand;
                            var fixedUp = BitConverter.GetBytes(newRelOffset);
                            fixedUp.ForEach((b, i) => m_ILStream()[i + addrOfOperand] = b);
                        };

                        var mode = GetOffsetsMode(br.Offset);
                        // see section #1 of the above comment
                        if (mode == OffsetsMode.Original)
                        {
                            // note. important: original offsets mode here 
                            // doesn't mean that the op processed has a corresponding preimage (see also n0te #3 above)
                            // it only means that the relative offset works in original mode

                            // step 1. find out orig_relOffset (note: trick here!)
                            var r_r_relOffset = br.RelativeTargetOffset;
                            var nearestOrig = _off2op[RewrittenToNearestOrig(br.Offset)];
                            var r_off2op = _rewrittenIL.ParseRawIL(module).ToDictionary(op => op.Offset, op => op);
                            var r_nearestOrig = r_off2op[OrigToRewritten(nearestOrig.Offset)];
                            var orig_relOffset = r_r_relOffset + (br.Offset - r_nearestOrig.Offset);

                            // step 2. restore the op that orig_relOffset references
                            var orig_pivot = nearestOrig.OffsetOfNextOp;
                            var orig_absOffset = orig_pivot + orig_relOffset;

                            // step 3. find out the r_pivot (note: trick here!)
                            var r_pivot = br.OffsetOfNextOp;

                            // step 4. calculate the r_relOffset
                            var r_absOffset = OrigToRewritten(orig_absOffset);
                            var r_relOffset = r_absOffset - r_pivot;

                            rewriteRelOffset(r_relOffset);
                        }
                        // see section #2 of the above comment
                        else if (mode == OffsetsMode.Rewritten)
                        {
                            // we can't use relOffset here 
                            // because the "where" condition will become really complex
                            // since we need to take into account both negative and positive rels
                            var absOffset = br.AbsoluteTargetOffset;
                            branchExpansionPoints
                                .Where(kvp => kvp.Key < br.AbsoluteTargetOffset)
                                .ForEach(kvp => absOffset += kvp.Value);

                            rewriteRelOffset(absOffset - pivot);
                        }
                        else
                        {
                            throw AssertionHelper.Fail();
                        }
                    }
                    else if (rop is Switch)
                    {
                        throw AssertionHelper.Fail();
                    }
                    else
                    {
                        // do nothing - this op ain't eligible for fixup
                    }
                }

                // Finalizing the operations
                // fill in the RewrittenOps
                _rewrittenIL = m_ILStream().Take(get_length()).ToArray();
                TraceRawIl(_rewrittenIL, 3);
                var opsAfterRewriting = _rewrittenIL.ParseRawIL(module).ToDictionary(op => op.Offset, op => op);
                foreach (var rop in _rewrittenOps.Keys.ToArray())
                {
                    var startOffset = OrigToRewritten(rop.Offset);
                    var endOffset = rop.Next == null ? int.MaxValue : OrigToRewritten(rop.Next.Offset);
                    var imageOps = opsAfterRewriting
                        .Where(kvp2 => startOffset <= kvp2.Key && kvp2.Key < endOffset)
                        .Select(kvp2 => kvp2.Value);

                    _rewrittenOps[rop] = imageOps.ToReadOnly();
                }
            }
        }
コード例 #5
0
        public static ILGenerator clone(this ILGenerator il, IILOp op)
        {
            // todo #1. also take into account that we need to update stacksize
            // todo #2. what is RecordTokenFixup()?

            // load some internals
            var methodBuilder = il.Get("m_methodBuilder").AssertCast <MethodBuilder>();
            var typeBuilder   = methodBuilder.Get("m_containingType").AssertCast <TypeBuilder>();
            var ilModule      = typeBuilder.Get("m_module").AssertCast <ModuleBuilder>();

            // if op has some prefixes, clone them first
            op.Prefixes.ForEach(prefix => il.clone(prefix));

            // hello, Shlemiel the Painter...
            var operand = op.BytesOfOperand.ToArray();

            // fixup metadata tokens
            // 1. if op doesn't have a module specified, we just crash
            // 2. if op references a module builder, we verify that ilgen references it too
            //    since as of .NET 3.5 you cannot resolve a token in module builder
            // 3. if op has a regular module, we proceed to fixup
            var opModule = op.Get("Module").AssertCast <Module>();

            opModule.AssertNotNull();

            if (opModule is ModuleBuilder)
            {
                (opModule == ilModule).AssertTrue();
            }
            else
            {
                int newToken;

                // prepare to process ldtokens
                var ldc        = op as Ldc;
                var ldc_value  = ldc == null ? null : ldc.Value;
                var ldc_member = null as MemberInfo;
                if (ldc_value != null)
                {
                    if (ldc_value is RuntimeTypeHandle)
                    {
                        var rth = (RuntimeTypeHandle)ldc_value;
                        ldc_member = Type.GetTypeFromHandle(rth);
                    }
                    else if (ldc_value is RuntimeMethodHandle)
                    {
                        var rmh = (RuntimeMethodHandle)ldc_value;
                        ldc_member = MethodBase.GetMethodFromHandle(rmh);
                    }
                    else if (ldc_value is RuntimeFieldHandle)
                    {
                        var rfh = (RuntimeFieldHandle)ldc_value;
                        ldc_member = FieldInfo.GetFieldFromHandle(rfh);
                    }
                }

                // process special case - ldtoken
                var operandType = op.OpSpec.OperandType;
                if (operandType == OperandType.InlineTok)
                {
                    ldc_member.AssertNotNull();
                    if (ldc_member is Type)
                    {
                        operandType = OperandType.InlineType;
                    }
                    else if (ldc_member is MethodBase)
                    {
                        operandType = OperandType.InlineMethod;
                    }
                    else if (ldc_member is FieldInfo)
                    {
                        operandType = OperandType.InlineField;
                    }
                    else
                    {
                        throw AssertionHelper.Fail();
                    }
                }

                // process all other cases
                switch (operandType)
                {
                case OperandType.InlineType:
                    var type = (ldc_member ?? op.GetOrDefault("Type") ?? op.GetOrDefault("Resolved")).AssertCast <Type>();
                    if (op.OpSpec.OpCode == OpCodes.Newarr)
                    {
                        type = type.GetElementType();
                    }
                    newToken = ilModule.GetTypeToken(type).Token;
                    operand  = BitConverter.GetBytes(newToken);
                    break;

                case OperandType.InlineField:
                    var field = (ldc_member ?? op.GetOrDefault("Field") ?? op.GetOrDefault("Resolved")).AssertCast <FieldInfo>();
                    newToken = ilModule.GetFieldToken(field).Token;
                    operand  = BitConverter.GetBytes(newToken);
                    break;

                case OperandType.InlineMethod:
                    // note 1. Module::GetMethodToken won't work here
                    // since it returns index of an entry in the MemberRef metadata table (0x0a)
                    // closed generic methods are stored a separate metadata table (MethodSpec, 0x2b)

                    var method         = (ldc_member ?? op.GetOrDefault("Method") ?? op.GetOrDefault("Ctor") ?? op.GetOrDefault("Resolved")).AssertCast <MethodBase>();
                    var getMethodToken = typeof(ILGenerator).GetMethod("GetMethodToken", BF.PrivateInstance);
                    newToken = (int)getMethodToken.Invoke(il, new Object[] { method, null, false });
                    operand  = BitConverter.GetBytes(newToken);
                    break;

                case OperandType.InlineString:
                    var @string = (op.GetOrDefault("Value") ?? op.GetOrDefault("Resolved")).AssertCast <String>();
                    newToken = ilModule.GetStringConstant(@string).Token;
                    operand  = BitConverter.GetBytes(newToken);
                    break;

                case OperandType.InlineSig:
                    // todo. implement this
                    throw AssertionHelper.Fail();

                case OperandType.InlineBrTarget:
                case OperandType.InlineI:
                case OperandType.InlineI8:
                case OperandType.InlineNone:
#pragma warning disable 612, 618
                case OperandType.InlinePhi:
#pragma warning restore 612, 618
                case OperandType.InlineR:
                case OperandType.InlineSwitch:
                case OperandType.InlineVar:
                case OperandType.ShortInlineBrTarget:
                case OperandType.ShortInlineI:
                case OperandType.ShortInlineR:
                case OperandType.ShortInlineVar:
                    // do nothing - operand ain't needs a fixup
                    break;

                default:
                    throw AssertionHelper.Fail();
                }
            }

            // write the op to the output stream
            return(il.raw(op.OpSpec.OpCode, operand));
        }
コード例 #6
0
 public static ILGenerator EmitClone(this ILGenerator il, IILOp op)
 {
     return(il.clone(op));
 }
コード例 #7
0
 // dispatch logic
 private void Dispatch(IILOp op)
 {
     switch (op.OpType)
     {
         case IILOpType.Nop:
             Process(op.AssertCast<Nop>());
             break;
         case IILOpType.Break:
             Process(op.AssertCast<CilBreak>());
             break;
         case IILOpType.Ldarg:
             Process(op.AssertCast<Ldarg>());
             break;
         case IILOpType.Ldloc:
             Process(op.AssertCast<Ldloc>());
             break;
         case IILOpType.Stloc:
             Process(op.AssertCast<Stloc>());
             break;
         case IILOpType.Ldarga:
             Process(op.AssertCast<Ldarga>());
             break;
         case IILOpType.Starg:
             Process(op.AssertCast<Starg>());
             break;
         case IILOpType.Ldloca:
             Process(op.AssertCast<Ldloca>());
             break;
         case IILOpType.Ldc:
             Process(op.AssertCast<Ldc>());
             break;
         case IILOpType.Dup:
             Process(op.AssertCast<Dup>());
             break;
         case IILOpType.Pop:
             Process(op.AssertCast<Pop>());
             break;
         case IILOpType.Call:
             Process(op.AssertCast<Call>());
             break;
         case IILOpType.Ldind:
             Process(op.AssertCast<Ldind>());
             break;
         case IILOpType.Stind:
             Process(op.AssertCast<Stind>());
             break;
         case IILOpType.Operator:
             Process(op.AssertCast<CilOperator>());
             break;
         case IILOpType.Cast:
             Process(op.AssertCast<Cast>());
             break;
         case IILOpType.New:
             Process(op.AssertCast<New>());
             break;
         case IILOpType.Initobj:
             Process(op.AssertCast<Initobj>());
             break;
         case IILOpType.Ldfld:
             Process(op.AssertCast<Ldfld>());
             break;
         case IILOpType.Ldflda:
             Process(op.AssertCast<Ldflda>());
             break;
         case IILOpType.Stfld:
             Process(op.AssertCast<Stfld>());
             break;
         case IILOpType.Ldlen:
             Process(op.AssertCast<Ldlen>());
             break;
         case IILOpType.Ldelema:
             Process(op.AssertCast<Ldelema>());
             break;
         case IILOpType.Ldelem:
             Process(op.AssertCast<Ldelem>());
             break;
         case IILOpType.Stelem:
             Process(op.AssertCast<Stelem>());
             break;
         case IILOpType.Ldftn:
             Process(op.AssertCast<Ldftn>());
             break;
         case IILOpType.Isinst:
             Process(op.AssertCast<Isinst>());
             break;
         case IILOpType.Sizeof:
             Process(op.AssertCast<CilSizeOf>());
             break;
         case IILOpType.Throw:
             Process(op.AssertCast<CilThrow>());
             break;
         case IILOpType.Rethrow:
             Process(op.AssertCast<CilRethrow>());
             break;
         case IILOpType.Localloc:
             throw AssertionHelper.Fail();
         case IILOpType.Arglist:
             throw AssertionHelper.Fail();
         case IILOpType.Mkrefany:
             throw AssertionHelper.Fail();
         case IILOpType.Refanyval:
             throw AssertionHelper.Fail();
         case IILOpType.Refanytype:
             throw AssertionHelper.Fail();
         case IILOpType.Initblk:
             throw AssertionHelper.Fail();
         case IILOpType.Cpblk:
             throw AssertionHelper.Fail();
         case IILOpType.Cpobj:
             throw AssertionHelper.Fail();
         case IILOpType.Jmp:
             throw AssertionHelper.Fail();
         case IILOpType.Ckfinite:
             throw AssertionHelper.Fail();
         default:
             throw AssertionHelper.Fail();
     }
 }
コード例 #8
0
 private Node _mapOp(IILOp op) { return _map.AssertSingle(kvp => ReferenceEquals(kvp.Value, op)).Key; }
コード例 #9
0
        public void DoRewrite()
        {
            _status.InProgress.AssertTrue();

            using (_status)
            {
                Func <byte[]> m_ILStream  = () => _il.Get("m_ILStream").AssertCast <byte[]>();
                var           typeBuilder = _dest.Get("m_containingType").AssertCast <TypeBuilder>();
                var           module      = typeBuilder.Get("m_module").AssertCast <ModuleBuilder>();
                Func <int>    get_length  = () => _il.Get("m_length").AssertCast <int>();
                Action <int>  set_length  = v => _il.Set("m_length", v);

                // Stage 1: Write rewritten ops according to _logic
                // So far we don't care about branches being fix't up
                var rawIl_BeforeStage1 = _src.ParseBody().RawIL;
                TraceRawIl(rawIl_BeforeStage1, 0);

                foreach (var op in _body)
                {
                    _curr = op;
                    _logic(op, this);
                }

                // Stage 2: Replace short branches with regular ones
                // since fixups (see below) might overflow the 1-byte offset storage
                _rewrittenIL = m_ILStream().Take(get_length()).ToArray();
                TraceRawIl(_rewrittenIL, 1);
                set_length(0);

                var fixupUpdates          = new List <Action>();
                var branchExpansionPoints = new Dictionary <int, int>();
                foreach (var rop in _rewrittenIL.ParseRawIL(module))
                {
                    var rop1 = rop;
                    if (rop1 is Branch)
                    {
                        var br = rop1.AssertCast <Branch>();
                        if (rop1.OpSpec.OperandType == OperandType.ShortInlineBrTarget)
                        {
                            // rewrite short branch to normal form
                            var opcode_sig = rop1.OpSpec.OpCode.Value + 0x0d;
                            var allOpcodes = typeof(OpCodes).GetFields(BF.PublicStatic).Select(f => f.GetValue(null).AssertCast <OpCode>());
                            var opcode     = allOpcodes.Single(oc => oc.Value == opcode_sig);
                            _il.raw(opcode, BitConverter.GetBytes(br.RelativeTargetOffset));

                            // update fixup of the next operation
                            // fixup = translate from original offsets to after-stage-2 ones
                            var preImage = _off2op[RewrittenToNearestOrig(rop1.Offset)];
                            if (preImage.Next != null)
                            {
                                fixupUpdates.Add(() => _fixups[preImage.Next] += 3);
                            }

                            // update the map that memorizes BEPs in after-stage-1 coordinates
                            fixupUpdates.Add(() => branchExpansionPoints[rop1.Offset] = 3);

                            // also be careful to fixup _offsetsModeChangeLog => lazily!
                            // fixup = translate from after-stage-1 to after-stage-2 coordinates
                            foreach (var entry in _offsetsModeChangeLog)
                            {
                                (rop1.Offset < entry.Offset && entry.Offset < rop1.OffsetOfNextOp).AssertFalse();

                                var entry1 = entry;
                                var fixup  = rop1.Offset >= entry1.Offset ? 0 : 3;
                                fixupUpdates.Add(() => entry1.Offset += fixup);
                            }
                        }
                        else
                        {
                            _il.clone(rop1);
                        }
                    }
                    else
                    {
                        _il.clone(rop1);
                    }
                }

                // we defer updates so that they won't f**k up _fixups in process
                fixupUpdates.RunEach();

                // Stage 3: Fixup branches since their offsets are most likely invalid now
                // todo. also fixup switches and protected regions
                //
                // note. this works as follows:
                // 1) if an instruction was emitted during OffsetsMode.Original,
                //    i.e. (if EnterXXXMode wasn't called) during Clone
                //    it needs a fixup and uses the main fixup log, i.e. _fixups.
                // 2) if an instruction was emitted during OffsetsMode.Rewritten,
                //    i.e. (if EnterXXXMode wasn't called) during Clone
                //    it ain't need a fixup due to rewriting,
                //    but does need a fixup to compensate for short branches expansion (see above)
                //    and thusly uses the branchExpansionFixups log
                _rewrittenIL = m_ILStream().Take(get_length()).ToArray();
                TraceRawIl(_rewrittenIL, 2);
                foreach (var rop in _rewrittenIL.ParseRawIL(module))
                {
                    // note #1.
                    // we can't use Target here since offsets are most likely broken at the moment
                    // at best it'll return null, and at worst it'll crash

                    // note #2.
                    // we can't use AbsoluteTargetOffset either since it positions at after-stage-2 IL
                    // but not to before-stage-1 IL (i.e. original)

                    // note #3.
                    // neither we can use RewrittenToOrig(rop.Offset)
                    // since, even if we're at OffsetsMode.Original, the rop might've been issued during r/w

                    if (rop is Branch)
                    {
                        var br    = rop.AssertCast <Branch>();
                        var pivot = br.OffsetOfNextOp;

                        Action <int> rewriteRelOffset = newRelOffset =>
                        {
                            var addrOfOperand = rop.OffsetOfOperand;
                            var fixedUp       = BitConverter.GetBytes(newRelOffset);
                            fixedUp.ForEach((b, i) => m_ILStream()[i + addrOfOperand] = b);
                        };

                        var mode = GetOffsetsMode(br.Offset);
                        // see section #1 of the above comment
                        if (mode == OffsetsMode.Original)
                        {
                            // note. important: original offsets mode here
                            // doesn't mean that the op processed has a corresponding preimage (see also n0te #3 above)
                            // it only means that the relative offset works in original mode

                            // step 1. find out orig_relOffset (note: trick here!)
                            var r_r_relOffset  = br.RelativeTargetOffset;
                            var nearestOrig    = _off2op[RewrittenToNearestOrig(br.Offset)];
                            var r_off2op       = _rewrittenIL.ParseRawIL(module).ToDictionary(op => op.Offset, op => op);
                            var r_nearestOrig  = r_off2op[OrigToRewritten(nearestOrig.Offset)];
                            var orig_relOffset = r_r_relOffset + (br.Offset - r_nearestOrig.Offset);

                            // step 2. restore the op that orig_relOffset references
                            var orig_pivot     = nearestOrig.OffsetOfNextOp;
                            var orig_absOffset = orig_pivot + orig_relOffset;

                            // step 3. find out the r_pivot (note: trick here!)
                            var r_pivot = br.OffsetOfNextOp;

                            // step 4. calculate the r_relOffset
                            var r_absOffset = OrigToRewritten(orig_absOffset);
                            var r_relOffset = r_absOffset - r_pivot;

                            rewriteRelOffset(r_relOffset);
                        }
                        // see section #2 of the above comment
                        else if (mode == OffsetsMode.Rewritten)
                        {
                            // we can't use relOffset here
                            // because the "where" condition will become really complex
                            // since we need to take into account both negative and positive rels
                            var absOffset = br.AbsoluteTargetOffset;
                            branchExpansionPoints
                            .Where(kvp => kvp.Key < br.AbsoluteTargetOffset)
                            .ForEach(kvp => absOffset += kvp.Value);

                            rewriteRelOffset(absOffset - pivot);
                        }
                        else
                        {
                            throw AssertionHelper.Fail();
                        }
                    }
                    else if (rop is Switch)
                    {
                        throw AssertionHelper.Fail();
                    }
                    else
                    {
                        // do nothing - this op ain't eligible for fixup
                    }
                }

                // Finalizing the operations
                // fill in the RewrittenOps
                _rewrittenIL = m_ILStream().Take(get_length()).ToArray();
                TraceRawIl(_rewrittenIL, 3);
                var opsAfterRewriting = _rewrittenIL.ParseRawIL(module).ToDictionary(op => op.Offset, op => op);
                foreach (var rop in _rewrittenOps.Keys.ToArray())
                {
                    var startOffset = OrigToRewritten(rop.Offset);
                    var endOffset   = rop.Next == null ? int.MaxValue : OrigToRewritten(rop.Next.Offset);
                    var imageOps    = opsAfterRewriting
                                      .Where(kvp2 => startOffset <= kvp2.Key && kvp2.Key < endOffset)
                                      .Select(kvp2 => kvp2.Value);

                    _rewrittenOps[rop] = imageOps.ToReadOnly();
                }
            }
        }
コード例 #10
0
 private Node _mapOp(IILOp op)
 {
     return(_map.AssertSingle(kvp => ReferenceEquals(kvp.Value, op)).Key);
 }
コード例 #11
0
ファイル: ILOp.cs プロジェクト: avaranovich/truesight-lite
 public bool Equals(IILOp other)
 {
     return(Equals(other as ILOp));
 }