Custom X86_64 calling convention to C function call - c

I've to do an interface (say, a wrapper) that allow a call from X86_64 assembly code using his calling convention to C function, with other calling convention. The best thing would be to be pretty "compiler independant" (juste modifying the wrapper), so i'm looking for something that puts registers/stack stuff on compiler back. I've already look here : Custom calling convention for P/Invoke and C# and it's come close from what i've to do. Currently, I'm using GCC, but hints from other compilers are welcome !
So, here is the thing, for a best view of the problem (the custom coding convention is strange ) :
pushq %r11 # saves r11 for call
movq 64bits_address %r11 # move a 64 bits address that points on a data structure
callq *8(%r11) # calls an address in the data structure
popq %r11 # restores %r11 ; return value is in the structure
I need to be able to call a "special" (wrapper) C function ; here job will be to dispatch calls between other C functions. So this wrapper needs to find %r11, save all registers and prepare the stack for further call. Is there a proper way to do this in C (with some inline asm) ?
Thanks a lot

For documentation about calling conventions and how are the parameter passed to a function (in registers? which? what's on the stack etc) have a look at Agner Fog's document.
Then, you can have a look at libffi's source code to see how they do it.

Related

Linking and calling printf from gas assembly

There are a few related questions to this which I've come across, such as Printf with gas assembly and Calling C printf from assembly but I'm hoping this is a bit different.
I have the following program:
.section .data
format:
.ascii "%d\n"
.section .text
.globl _start
_start:
// print "55"
mov $format, %rdi
mov $55, %rsi
mov $0, %eax
call printf # how to link?
// exit
mov $60, %eax
mov $0, %rdi
syscall
Two questions related to this:
Is it possible to use only as (gas) and ld to link this to the printf function, using _start as the entry point? If so, how could that be done?
If not, other than changing _start to main, what would be the gcc invocation to run things properly?
It is possible to use ld, but not recommended: if you use libc functions, you need to initialise the C runtime. That is done automatically if you let the C compiler provide _start and start your program as main. If you use the libc but not the C runtime initialisation code, it may seem to work, but it can also lead to strange spurious failure.
If you start your program from main (your second case) instead, it's as simple as doing gcc -o program program.s where program.s is your source file. On some Linux distributions you may also need to supply -no-pie as your program is not written in PIC style (don't worry about this for now).
Note also that I recommend not mixing libc calls with raw system calls. Instead of doing a raw exit system call, call the C library function exit. This lets the C runtime deinitialise itself correctly, including flushing any IO streams.
Now if you assemble and link your program as I said in the first paragraph, you'll notice that it might crash. This is because the stack needs to be aligned to a multiple of 16 bytes on calls to functions. You can ensure this alignment by pushing a qword of data on the stack at the beginning of each of your functions (remember to pop it back off at the end).

What is the use of _start() in C?

I learned from my colleague that one can write and execute a C program without writing a main() function. It can be done like this:
my_main.c
/* Compile this with gcc -nostartfiles */
#include <stdlib.h>
void _start() {
int ret = my_main();
exit(ret);
}
int my_main() {
puts("This is a program without a main() function!");
return 0;
}
Compile it with this command:
gcc -o my_main my_main.c –nostartfiles
Run it with this command:
./my_main
When would one need to do this kind of thing? Is there any real world scenario where this would be useful?
The symbol _start is the entry point of your program. That is, the address of that symbol is the address jumped to on program start. Normally, the function with the name _start is supplied by a file called crt0.o which contains the startup code for the C runtime environment. It sets up some stuff, populates the argument array argv, counts how many arguments are there, and then calls main. After main returns, exit is called.
If a program does not want to use the C runtime environment, it needs to supply its own code for _start. For instance, the reference implementation of the Go programming language does so because they need a non-standard threading model which requires some magic with the stack. It's also useful to supply your own _start when you want to write really tiny programs or programs that do unconventional things.
While main is the entry point for your program from a programmers perspective, _start is the usual entry point from the OS perspective (the first instruction that is executed after your program was started from the OS)
In a typical C and especially C++ program, a lot of work has been done before the execution enters main. Especially stuff like initialization of global variables. Here you can find a good explanation of everything that's going on between _start() and main() and also after main has exited again (see comment below).
The necessary code for that is usually provided by the compiler writers in a startup file, but with the flag –nostartfiles you essentially tell the compiler: "Don't bother giving me the standard startup file, give me full control over what is happening right from the start".
This is sometimes necessary and often used on embedded systems. E.g. if you don't have an OS and you have to manually enable certain parts of your memory system (e.g. caches) before the initialization of your global objects.
Here is a good overview of what happens during program startup before main. In particular, it shows that __start is the actual entry point to your program from OS viewpoint.
It is the very first address from which the instruction pointer will start counting in your program.
The code there invokes some C runtime library routines just to do some housekeeping, then call your main, and then bring things down and call exit with whatever exit code main returned.
A picture is worth a thousand words:
P.S: this answer is transplanted from another question which SO has helpfully closed as duplicate of this one.
When would one need to do this kind of thing?
When you want your own startup code for your program.
main is not the first entry for a C program, _start is the first entry behind the curtain.
Example in Linux:
_start: # _start is the entry point known to the linker
xor %ebp, %ebp # effectively RBP := 0, mark the end of stack frames
mov (%rsp), %edi # get argc from the stack (implicitly zero-extended to 64-bit)
lea 8(%rsp), %rsi # take the address of argv from the stack
lea 16(%rsp,%rdi,8), %rdx # take the address of envp from the stack
xor %eax, %eax # per ABI and compatibility with icc
call main # %edi, %rsi, %rdx are the three args (of which first two are C standard) to main
mov %eax, %edi # transfer the return of main to the first argument of _exit
xor %eax, %eax # per ABI and compatibility with icc
call _exit # terminate the program
Is there any real world scenario where this would be useful?
If you mean, implement our own _start:
Yes, in most of the commercial embedded software I have worked with, we need to implement our own _start regarding to our specific memory and performance requirements.
If you mean, drop the main function and change it to something else:
No, I don't see any benefit doing that.

OS Architecture: Kernel and Standard Library interoperability

As always I thank you for your time and effort in assisting me on my journey :)
So being a nerd I have started pulling back the layers of how the OS works. Where I have a question is around the kernel and the standard libraries, such as glibc for Linux, which acts as a function wrapper.
Why does the OS need a standard library which is written in C? OR asked another way Could you write a standard library for the Linux kernel in another language other than C?
I assume that and that the language of the STD library may be dependent on the language chosen for the Kernel. So in our example of Linux, which is written in C, the wrapper STD library also needed to be C.
I understand why the kernel needs the STD library in general so that isn't really what I am trying to get at JIC I wasn't clear.
Thanks Again!
Let's dive in more details about OS - userspace communication. Do you know how it goes? Basically each platform uses its own approach to make a so called syscall -> control transfer from userspace to kernelspace.
For example x86 uses int instruction, x86-64 uses syscall instruction, arm uses swi and so on. Also each platform has its own understanding of how parameters and syscall number should be established before syscall instruction is called. Let's focus on x86-64:
For example for calling execve (syscall number 0x3b) this code is enough. You can try it.
section .text
global _start
_start:
mov rax, 0x3b
mov rdi, cmd
mov rsi, 0
mov rdx, 0
syscall
section .data
cmd: db '/bin/sh'
.end:
Now let's understand what is execve libc function. Basically if you will dive into libc code, you will see that it is wrapper which leads to syscall function (see syscall.S for your arch in libc). This syscall.S looks pretty same with our example above:
.text
ENTRY (syscall)
movq %rdi, %rax /* Syscall number -> rax. */
movq %rsi, %rdi /* shift arg1 - arg5. */
movq %rdx, %rsi
movq %rcx, %rdx
movq %r8, %r10
movq %r9, %r8
movq 8(%rsp),%r9 /* arg6 is on the stack. */
syscall /* Do the system call. */
So basically, as user4098326 and rcgldr have mentioned - the interconnection between uspace and kernel is assembly code, and all things above it - just wrappers. So as i understand all this wrappers could be written not only in C.
General kernel driver works through file operations, like open, close, read, & write.
Again, as kernel is also written completely in C.
So due to these 2 reasons
, I think, we can not write lower level library calls in other language.

Is it possible to convert C to asm without link libc on Linux?

Test platform is on Linux 32 bit. (But certain solution on windows 32 bit is also welcome)
Here is a c code snippet:
int a = 0;
printf("%d\n", a);
And if I use gcc to generate assembly code
gcc -S test.c
Then I will get:
movl $0, 28(%esp)
movl 28(%esp), %eax
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call printf
leave
ret
And this assembly code needs linking to libc to work(because of the call printf)
My question is :
Is it possible to convert C to asm with only explicit using system call automatically, without using libc?
Like this:
pop ecx
add ecx,host_msg-host_reloc
mov eax,4
mov ebx,1
mov edx,host_msg_len
int 80h
mov eax,1
xor ebx,ebx
int 80h
Directly call the int 80h software interrupt.
Is it possible? If so, is there any tool on this issue?
Thank you!
Not from that source code. A call to printf() cannot be converted by the compiler to a call to the write system call - the printf() library function contains a significant amount of logic which is not present in the system call (such as processing the format string and converting integer and floating-point numbers to strings).
It is possible to generate system calls directly, but only by using inline assembly. For instance, to generate a call to _exit(0) (not quite the same as exit()!), you would write:
#include <asm/unistd.h>
...
int retval;
asm("int $0x80" : "=a" (retval) : "a" (__NR_exit_group), "b" (0) : "memory");
For more information on GCC inline assembly, particularly on the constraints I'm using here to map variables to registers, please read the GCC Inline Assembly HOWTO. It's rather old, but still perfectly relevant.
Note that doing this is not recommended. The exact calling conventions for system calls (e.g, which registers are used for the call number and arguments, how errors are returned, etc) are different on different architectures, operating systems, and even between 32-bit and 64-bit x86. Writing code this way will make it very difficult to maintain.
You can certainly compile C code to assembly without linking to libc, but you can't use the C library functions. Libc's entire purpose IS to provide the interface from C library functions to Linux system calls (or Windows, or whatever system you're on). So, if you didn't want to use libc, you would have to write your own wrappers to the system calls.
If you compile some C code which does not use any function from the C library (e.g. does not use printf or malloc etc etc....) in the free-standing mode of the GCC compiler (i.e. with -ffreestanding flag to gcc), you'll need either to call some assembler function (from some other object or library) or to use asm instruction (you won't be able to do any kind of input output without making a syscall).
Read also the Assembly HowTo, the x86 calling conventions and the ABI relevant to your kernel (probably x86-64 ABI) and understand quite well what are system calls, starting with syscalls(2) and what is the VDSO (int 80 is not the best way to make syscalls these days, SYSENTER is often better). Study the source code of some libc, in particular of MUSL libc (whose source code is very readable).
On Windows (which is not free software and which I don't know) the question could be much more difficult: I am not sure that the system call level is exactly and completely documented.
The libffi enables you to call arbitrary functions from C. You could also cast function pointers from dlsym(3). You could consider JIT techniques (e.g. libjit, GNU lightning, asmjit etc...).

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

I am writing a C function that will be invoked from assembly code.
(Specifically, I want to do some checking job in the path of system call handling in linux kernel, so I will call the c function before a system call is dispatched in entry_32.S)
I am confused with the "asmlinkage" modifier when defining my c function.
I know asmlinkage is to tell the compiler that the parameters will be passed through stack.
#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))
Questions:
(1) Is asmlinkage required when defining such a function that will be invoked from assembly code?
(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?)
(4) why are those system call functions all declared with asmlinkage. Can we copy the parameters to registers first, then call those system call functions? From my point of view, in x86, when issuing a system call, the parameters are readily saved in registers; then why bother to save then in stack to enforce such passing parameters via stack convention?
Finally, can anybody recommend some resources/books that I can refer to for such mix assembly/c programming?
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.
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.

Resources