从全局内联汇编调用静态函数

Pau*_*aul 5 c assembly gcc inline-assembly

我试图定义一个没有任何序言/结尾的函数,一个“到达地址”,以便它可以调用由编译器正确管理的内部函数(对调用者清除环境有用)。

我发现可以使用内联汇编程序创建全局标签,但是在同一文件中调用另一个函数时遇到问题。当我按此处列出的顺序编译代码时,我收到警告:

警告:“ handle_vmexit” [/代码/超级/内核/hyper.ko]未定义!

当我删除静态修饰符时,没有任何问题。

所以我的问题是,为什么嵌入式程序集在静态时无法与handle_vmexit链接,以及如何使其称为静态handle_vmexit。

以下是相关代码:

static void handle_vmexit(void){
    ...
}

__asm__(".handle_vmexit: \n\t"
    "call handle_vmexit"
);
Run Code Online (Sandbox Code Playgroud)

use*_*170 6

声明C函数时static,其他转换单元看不到C函数,因此C编译器假定它可以看到其每次使用,并根据该假设做出优化决策。如果未使用该函数,则编译器可能无法完全为其发出代码;如果仅使用一次,则可以将其内联到其唯一的调用方中,而不必单独发出其符号(GCC选项-finline-functions-called-once),依此类推。即使您自己不使用inline关键字(选项-finline-functions),编译器甚至可能决定内联所有调用。*

但是,GCC无法检测到内联汇编中的用法。汇编代码对GCC完全不透明。要强制编译器无论如何都要为此函数分别发出代码,请使用__attribute__((used)); 该属性是专门为此添加的。本手册对属性的描述如下:

used
附加到函数的此属性意味着,即使看起来未引用该函数,也必须为该函数发出代码。例如,仅在内联汇编中引用该功能时,此功能很有用。

当应用于C ++类模板的成员函数时,该属性还意味着,如果实例化了类本身,则实例化该函数。


*严格来说,即使函数的代码是单独发出的,编译器也可以完全不用在生成的汇编文件中声明通常的命名符号,而可以通过一些不透明的,人工生成的标识符来引用该函数,就像它一样与标签。但是我认为海湾合作委员会将永远不可能利用这种自由,特别是如果采用这里给出的解决方案。