Page 1 of 1
User side of system calls
Posted: Mon Apr 30, 2012 2:45 pm
by justin
How do you implement system calls on the user's end? I was going to borrow the linux _syscall macros which a copied from an old unistd.h:
Code: Select all
#define _syscall0(type,name) \
type name(void) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name)); \
if (__res >= 0) \
return (type) __res; \
errno = -__res; \
return -1; \
}
But I'm not getting it to compile and I was wondering if there is a better way.
Re: User side of system calls
Posted: Mon Apr 30, 2012 3:13 pm
by AndrewBuckley
code seems strait forward to me. but it only works if your syscall interface works the same.
1)the code calls int 0x80 (linux syscall)
2)checks the result if its a positive number. if positive or 0 things went well return result.
if negative there was an error. set errno the value given as a positive number, and return -1.
at the very least errno must be defined somewhere.
you should understand what code does before you try to use it.
Re: User side of system calls
Posted: Mon Apr 30, 2012 4:41 pm
by bluemoon
justin wrote:How do you implement system calls on the user's end?
My 32-bit kernel uses INT 80 style syscall, where eax=function number, ebx, ecx, edx, esi, edi can be used as #1, #2, #3... parameters. return value are returned with eax, edx(2nd return)
For example:
Code: Select all
section .text
; ----------------------------------------------
; int _exit (int exit_code);
_exit:
push ebx
mov eax, 1
mov ebx, [esp+8]
int 0x80
pop ebx
ret
; ----------------------------------------------
; int open ( const char * file, int flags, int mode );
open:
push ebx
push ecx
push edx
mov ebx, [esp+16] ; file
mov ecx, [esp+20] ; flags
mov edx, [esp+24] ; mode
mov eax, 2
int 0x80
pop edx
pop ecx
pop ebx
ret
I'm currently working on 64-bit kernel and plan to use syscall/sysret instead of INT, they should be quite simular using registers for communication.
Re: User side of system calls
Posted: Mon Apr 30, 2012 4:42 pm
by justin
Merlin wrote:code seems strait forward to me. but it only works if your syscall interface works the same.
1)the code calls int 0x80 (linux syscall)
2)checks the result if its a positive number. if positive or 0 things went well return result.
if negative there was an error. set errno the value given as a positive number, and return -1.
at the very least errno must be defined somewhere.
you should understand what code does before you try to use it.
I understand what it does. That's not the problem.
Re: User side of system calls
Posted: Mon Apr 30, 2012 4:59 pm
by justin
I ran gcc -E on my source file and apparently the preprocessor is not expanding the _SYSCALL0 macro.
I have this in my source file:
Code: Select all
int errno;
_SYSCALL0(int,endthread)
I include a file with:
Code: Select all
#define __NR_endthread 0x1
extern int errno;
#define _syscall0(type,name) \
type name(void) \
{ \
long __res; \
__asm__ volatile ("int $0x40" \
: "=a" (__res) \
: "0" (__NR_##name)); \
if (__res >= 0) \
return (type) __res; \
errno = -__res; \
return -1; \
}
and then I get these errors:
Code: Select all
thread.c:299: error: expected declaration specifiers or ‘...’ before ‘endthread’
cc1: warnings being treated as errors
thread.c:299: error: return type defaults to ‘int’
thread.c: In function ‘_SYSCALL0’:
thread.c:299: error: parameter name omitted
thread.c:299: error: expected ‘{’ at end of input
Anybody know why the macro might not work?
Re: User side of system calls
Posted: Mon Apr 30, 2012 5:01 pm
by justin
I see it now, I wrote SYSCALL when it is syscall.
Re: User side of system calls
Posted: Mon Apr 30, 2012 6:09 pm
by AndrewAPrice
Link with a syscall library and upon your first system call all of your functions jump to a handler that detect if the CPU supports sysenter, syscall, or fallback to int. Then overwrite each of the syscall functions with the most optimal handler for that CPU.