/// <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); }