Is “asmlinkage” required for a c function to be called from assembly?

穿精又带淫゛_ 提交于 2019-11-28 18:50:51
Infinite

After several hours' research, I got the following empirical points:

(1) Is asmlinkage required when defning such a function that will be invoked from assembly code?

No. Actually the fastcall is frequently used.

For example, in entry_32.S, if you search "call", you can obtain all the c functions invoked from this assembly file. Then you can see, many use fastcall instead of asmlinkage as the calling convention. For example,

    /*in entry_32.S*/
    movl PT_OLDESP(%esp), %eax
    movl %esp, %edx
    call patch_espfix_desc

    /*in traps_32.c*/
    fastcall unsigned long patch_espfix_desc(unsigned long uesp,
                  unsigned long kesp)

(2) what is the default calling convention in gcc. If I omit "asmlinkage" when defining a c function, does it imply _cdecl or fastcall?

(3) if the default calling convention is cdecl, why is asmlinkage needed, considering cdecl is equal to asmlinkage modifier? (am I correct here?)

For C functions not invoked from assembly code, we can safely assume the default calling convention is cdecl (or fast call; it doesn't matter, because gcc will take care of the caller and callee for parameter passing. The default calling convention can be specified when compiling). However, for C functions invoked from assembly code, we should explicitly declare the function's calling convention, because the parameter passing code in assembly side has been fixed. For example, if patch_espfix_desc is declared as asmlinkage, then gcc will compile the function to retrieve parameters from stack. This is inconsistent with the assembly side, which put the parameters into registers.

But I am still not clear when to use asmlinkage and when to use fastcall. I really need some guideline and resources to refer to.

Infinite

I would like to try to answer question (4) myself:

Why do all the system call functions sys_*, e.g. sys_gettimeofday, use stack to pass parameters?

The reason is that anyhow the kernel needs to save all the registers onto stack (in order to restore the environment before returning to the userspace) when handling the system call requests from userspace, so after that the parameters are available on stack. I.e., it doesn't need extra effort.

On the other hand, if you want to use fastcall for the calling convention, more work has to be done. We first need to know, when a user program issues a system call, in x86-linux, %eax is for syscall number, and %ebx, %ecx, %edx, %esi, %edi, %ebp are used for passing 6 parameters to system calls (before "int 80h" or "sysenter"). However, the calling convention of fastcall is to pass the first parameter in %eax, the 2nd one in %edx, the 3rd %ecx, others are pushed onto stack from right to left. In this way, to enforce such fastcall convention in kernel, you need to somehow arrange these in addition to save all the registers on the stack.

The idea, I believe, is to allow the kernel to be compiled with gcc options that would change the default calling convention to something more efficient (i.e. passing more arguments in registers). However, functions that need to be called from asm cannot be allowed to vary in calling convention based on the gcc options in use, or there would have to be separate versions of the asm for every supported set of gcc options. Thus, functions that need to use a fixed calling convention (which happens to match the default with no special gcc options) are declared with special attributes so that their calling convention will remain fixed.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!