【问题标题】:gcc option: get start and end addresses of inline functionsgcc 选项:获取内联函数的开始和结束地址
【发布时间】:2010-10-18 15:31:51
【问题描述】:

我的问题很明确:

使用-O2时如何获取内联函数的编译指令?我尝试使用 readelf 来获取源代码行和二进制代码地址之间的映射。但是调用内联函数的那一行根本没有映射。

那么,可以使用什么编译器选项或任何方法?

事实上,我觉得必须有办法告诉 gcc 转储所有函数的开始和结束地址。有人有线索吗? 谢谢!

---

让我重新表述我的意图: 我想配置 gcc 以便它可以告诉我从哪个函数编译了一组指令。是的,就是这样。

【问题讨论】:

  • 能否请您澄清一下,“函数的结束地址”是什么意思,您将如何使用它?

标签: gcc


【解决方案1】:

如果文件是内联的,则它没有开始和结束功能。每次调用它时,整个代码都会在它被调用的地方复制。这就是内联的目的。

每次调用时,都会有不同的开始地址和结束地址。这就是没有映射的原因。

如果您要做的只是提取该函数的程序集,则不要将其设为内联,然后您将能够准确地看到它。但是,根据编译器优化代码的方式,这可能与内联函数时生成的程序集并不完全相同。

【讨论】:

    【解决方案2】:

    由于函数是内联,它不再是一个单一的开始和结束的普通函数。它的主体已被插入到任何你调用它的地方。

    【讨论】:

      【解决方案3】:

      GCC 通常不会为内联函数生成代码(在高优化级别)。因为内联函数应该内联到它们的调用者中,并且将它们的代码保存在目标文件中是没有意义的。

      但是,这不是 C++ 标准所要求的。 C++ 标准要求函数指针可以指向任何函数,包括那些内联函数!但是函数指针在 GCC 中有一个具体的表示,它是一个指向物理位置的指针。这意味着,要使用指向内联函数的指针,它应该有一个特定的地址。

      所以,要获取内联函数的地址,你应该,嗯... 在代码中获取它的地址! 这将使编译器实例化内联函数并为它发出汇编代码。并且有更多的方式来发射他们的身体。见GCC docs:

      ...由于各种原因,某些[对内联函数的]调用无法集成(特别是,函数定义之前的调用无法集成,定义中的递归调用也不能集成)。如果有一个非集成调用,那么该函数像往常一样被编译为汇编代码。如果程序引用它的地址,该函数也必须像往常一样编译,因为它不能被内联。

      这是确认这一点的片段代码:

      inline int uiopuiop()
      {
        return 4;
      }
      typedef int (*fptr)();
      int main()
      {
        fptr f = uiopuiop;
        return uiopuiop();
      }
      

      如果你编译 C 代码,你也可以将-fkeep-inline-functions 用于static-inline 函数。

      【讨论】:

        【解决方案4】:

        内联函数不仅(通常)是内联的,而且各种优化都是在内联之后完成的。例如,如果sum 是两个整数相加的明显内联函数,则sum(3,4) 被7 替换,并且程序中不会出现对sum 的调用,你甚至不能给它一个位置。

        因此,您真的不想知道对内联函数的内联调用。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-05-24
          • 1970-01-01
          • 2013-05-09
          • 2013-07-24
          • 1970-01-01
          • 2011-11-14
          相关资源
          最近更新 更多