Beispiel #1
0
        /// <summary>
        /// Creates a small basic block, consisting solely of a 'call' followed by a 'return'
        /// instruction.
        /// </summary>
        /// <remarks>
        /// This is done when encountering tail calls (i.e. jumps) from one
        /// procedure into another.
        /// </remarks>
        /// <param name="addrFrom"></param>
        /// <param name="procOld"></param>
        /// <param name="procNew"></param>
        /// <returns></returns>
        public Block CreateCallRetThunk(Address addrFrom, Procedure procOld, Procedure procNew)
        {
            //$BUG: ReturnAddressOnStack property needs to be properly set, the
            // EvenOdd sample shows how this doesn't work currently.
            var blockName = string.Format(
                "{0}_thunk_{1}",
                Program.NamingPolicy.BlockName(addrFrom),
                procNew.Name);
            var callRetThunkBlock = procOld.AddSyntheticBlock(
                addrFrom,
                blockName);

            if (Program.User.BlockLabels.TryGetValue(blockName, out var userLabel))
            {
                callRetThunkBlock.UserLabel = userLabel;
            }

            var linFrom = addrFrom.ToLinear();

            callRetThunkBlock.Statements.Add(
                linFrom,
                new CallInstruction(
                    new ProcedureConstant(Program.Platform.PointerType, procNew),
                    new CallSite(0, 0)));
            Program.CallGraph.AddEdge(callRetThunkBlock.Statements.Last !, procNew);

            callRetThunkBlock.Statements.Add(linFrom, new ReturnInstruction());
            procOld.ControlGraph.AddEdge(callRetThunkBlock, procOld.ExitBlock);
            SetProcedureReturnAddressBytes(procOld, procNew.Frame.ReturnAddressSize, addrFrom);
            return(callRetThunkBlock);
        }