Reputation: 51
I am in process of adding system calls to linux Kernel 3.19. Tried out the following for adding a syscall 'add' for x86 arch in Ubuntu 14.04 LTS. src=3.19 source
Added entry to src/arch/x86/syscalls/syscall_64.tbl.
323 common add sys_add
Added syscall prototype to src/include/syscalls.h.
asmlinakge sys_add(int i,int j);
Wrote add.c in fs directory, added add.o in fs/Makefile .
In file src/include/uapi/asm-generic/unistd.h
Added lines
#define __NR_add 323
__SYSCALL(__NR_add, sys_add);
Compiled and built the kernel. It was success. The output of uname -r gives 3.19.
Created a program to test new syscall.
6.1 Used the function syscall(323,10,15). It was success as the sum of values(25) was printed.
6.2 When trying to call syscall by name, it gives
/tmp/ccpxRp8C.o: In function `main':
testadd1.c:(.text+0x18): undefined reference to `add'
collect2: error: ld returned 1 exit status
What am I missing??
Upvotes: 4
Views: 1071
Reputation:
You are missing the little piece of assembly code that, when assembled, shows up as a C-linkable symbol.
If you do this:
ar t /usr/lib/libc.a | grep write.o
you will see that the (statically-linkable) C library has a small file named "write.o". This contains a little piece of assembled code that defines a symbol __libc_write
that's visible outside of write.o
. That little piece of assembled code puts the value 1 in a specific register, which is the number that Linux and Unix kernels know as the "write" system call, sets up other registers very carefully, then executes a syscall
instruction (on my x86_64 machine).
You will have to create just such a piece of assembly code for your "add" system call. Or, you can you the syscall
system call, just as you have been doing, writing a plain C function to make it look lke you've got an add()
system call.
You don't say what architecture (x86 or x86_64) you're using, but here's an x86_64 implementation of write(2)
. It does set errno
correctly, and it returns the number of bytes written, but the argument types aren't correct.
int
linux_write(int fd, const void *data, unsigned long len)
{
long ret;
asm volatile ("syscall" : "=a" (ret) : "a" (__NR_write),
"D" (fd), "S" (data), "d" (len) :
"cc", "memory", "rcx",
"r8", "r9", "r10", "r11" );
if (ret < 0)
{
errno = -ret;
ret = -1;
}
return (int)ret;
}
Upvotes: 1