【问题标题】:why the Number of ret instructions is greater than number of call instructions?为什么 ret 指令的数量大于调用指令的数量?
【发布时间】:2018-01-02 01:40:30
【问题描述】:

我写了一个pintool。它在执行指令时为程序实现堆栈。如果遇到调用指令,它将按顺序将下一条指令的地址压入堆栈。当被调用的过程完成并遇到返回指令时,它会验证 ret 指令中的目标地址是否等于栈顶并弹出栈顶。

通常调用指令的数量应该等于返回指令的数量。但是这个工具会监控大量的返回指令。这怎么可能?问题是什么?我该如何解决?

编辑 1:

pintool的代码

VOID f_jump(int a, int b) 
{ 
s.push(b); 
cout<<s.top()<<"\t"; 
icount1++; 
}
VOID f_ret(int a, int b) 
{ 
if (b==s.top())
 { 
   cout<<s.top(); 
   s.pop(); 
   cout<<"\tOK"<<endl; 
 }
else 
cout<<"Exploit\t"<<endl<<s.top()<<"\t"<<b<<endl; 
icount2++; 
} 

VOID Instruction(INS ins, VOID *v) 
{ 
if( INS_IsCall(ins) ) 
  { 
  INS_InsertCall(ins,IPOINT_TAKEN_BRANCH,AFUNPTR(f_jump),
  IARG_BRANCH_TARGET_ADDR,IARG_RETURN_IP, IARG_END); 
  } 
if( INS_IsRet(ins) )
  { 
 INS_InsertCall(ins,IPOINT_BEFORE,AFUNPTR(f_ret),
 IARG_INST_PTR,IARG_BRANCH_TARGET_ADDR, IARG_END);
  } 
}

我在各种二进制文件和进程上运行它,但问题仍然存在。请帮忙。

【问题讨论】:

  • 一个函数只能有一个入口点(调用的目标),但可以有多个出口点(ret指令)。
  • 问:您是否尝试过生成程序集输出(例如gcc -S)并检查程序集源?问:如果函数碰巧有多个“返回”退出,您的工具会“检测”多个“RET”调用吗?在我们推测之前,我们真的需要更多信息......
  • 从技术上讲,编译器可以通过组合 pushs 和 jmps 来解决没有 calls 的问题。在某些情况下,这可能对性能有好处。不过,我不知道您的编译器是否适合这种黑客行为。关于您的评论,我认为其他人假设您在谈论分析程序集输出,而不是实际执行路径。
  • 从技术上讲,编译器还可以使用ret 指令来生成跳转,例如如push &lt;some address&gt;, ret。如果需要动态跳转目标但没有可用于基于寄存器的跳转的可用寄存器,这会很方便。不过,这种情况非常罕见。
  • @Prof,您将不得不发布一些代码:pintool 的简短版本,以及您运行它的程序。

标签: c++ operating-system cpu-architecture intel-pin


【解决方案1】:

您可以在函数调用中出现 longjmp、C++ 异常或退出调用,这会使您错过该函数调用的返回指令。

这个已经讨论过很多次了here

【讨论】:

  • jmp 尾调用会跳过 callret。此外,call / ret动态 计数通常应该匹配,不是吗? (或者这个 PIN 工具是否在做静态指令计数?)一个函数的多个调用站点与一个函数的多个返回路径只影响静态指令平衡,而不是动态。
  • 我的经验是 call/ret 的动态计数永远不会匹配,需要进行处理以协调这些数字。 PIN 新闻组(yahoogroup)充满了关于这个问题的讨论。我不知道你对“jmp”尾调用的意思是跳过一个调用和一个 ret。我更新了我的示例,因为您评论的第二部分是正确的。
  • 我以为您的最后一段是在讨论int foo() { return bar(); } 这样的案例,其中foo 编译为jmp bar 而不是call bar; ret。即优化的尾调用。在这种情况下,call 少了 1 次,ret 少了 1 次,所以余额不受影响。您尾调用的函数中的ret 仍然执行,并且它不会使硬件返回地址预测器堆栈失衡。 (我想如果你只是在检测一些功能,例如不是库,那么即使这不是性能问题,这也可能会导致 PIN 计数差异。)
  • 这不是一个很好的例子。我删除了它并添加了更多参考。
猜你喜欢
  • 2013-12-06
  • 1970-01-01
  • 2017-09-04
  • 2013-02-26
  • 1970-01-01
  • 2018-11-01
  • 2013-04-05
  • 2022-12-06
  • 1970-01-01
相关资源
最近更新 更多