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

Calling a static function from global inline assembly

我正在尝试定义一个没有任何 prologues/epilogues 的函数,一个 "landing address" 以便它可以调用由编译器正确管理的内部函数(对调用者清理环境很有用) .

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

WARNING: "handle_vmexit" [/Code/hyper/kernel/hyper.ko] undefined!

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

所以我的问题是,为什么内联程序集在静态时无法 link 和 handle_vmexit,我怎样才能让它调用静态的 handle_vmexit.

相关代码如下:

static void handle_vmexit(void){
    ...
}

__asm__(".handle_vmexit: \n\t"
    "call handle_vmexit"
);

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

但是,GCC 无法检测内联汇编中的用法;汇编代码对 GCC 是完全不透明的。要强制编译器单独为该函数发出代码,请使用 __attribute__((used));该属性是专门为此目的添加的。说明书describes the attribute如下:

used
This attribute, attached to a function, means that code must be emitted for the function even if it appears that the function is not referenced. This is useful, for example, when the function is referenced only in inline assembly.

When applied to a member function of a C++ class template, the attribute also means that the function is instantiated if the class itself is instantiated.


* 严格来说,即使函数的代码是单独发出的,编译器也可以完全不在生成的汇编文件中声明通常的命名符号,而是通过一些不透明的、人为的引用函数生成的标识符,就像标签一样。但我认为 GCC 不太可能利用这种自由,特别是如果应用此处给出的解决方案。