Page 1 of 1
[Newlib] Problem with syscall arguments
Posted: Sat Dec 24, 2011 12:48 pm
by fiveayem
Hello,
Having ported Newlib for my OS, I can not make any program work for one simple reason : syscalls are not made correctly. Let's explain. To make a syscall, I use an array of variable size, where I store all required parameters, and then I put the address of this array into ECX register in order the syscall handler can fetch the parameters.
So the only role of the syscall functions I wrote for Newlib was to fill arrays with various parameters, and to raise INT 30h to do a syscall. However, when disassembling the binary, I noticed that the program did not go fetching the arguments on the stack to put them into the array. I first thought that it was due to the fact that GCC thought that my array was unused, and thus "optimized" by not filling it. However, adding __attribute__((used)) did not change anything.
Any idea of where this problem comes from ?
Thanks for your help.
Re: [Newlib] Problem with syscall arguments
Posted: Sat Dec 24, 2011 4:52 pm
by gerryg400
I'm not exactly sure what you mean. Perhaps show a little code...
Re: [Newlib] Problem with syscall arguments
Posted: Sat Dec 24, 2011 6:15 pm
by Jezze
Paging problem? The array might have a virtual address not corresponding to the physical one seen by the operating system?
Re: [Newlib] Problem with syscall arguments
Posted: Sun Dec 25, 2011 8:50 am
by fiveayem
For instance, let's consider fstat() syscall :
C code :
Code: Select all
int fstat(int file, struct stat *st)
{
int params[2]; int* param_ptr = params;
int ret = 0; int* ret_ptr = &ret;
params[0] = file;
params[1] = (int)st;
vlos_do_syscall(SYSCALL_FSTAT, param_ptr, ret_ptr);
return ret;
}
// syscall macro
#define vlos_do_syscall(sysc_num, param, ret) \
__asm__ __volatile__("push %%eax \n\t \
push %%ebx \n\t \
push %%ecx \n\t \
mov %0, %%eax \n\t \
mov %1, %%ebx \n\t \
mov %2, %%ecx \n\t \
int $0x30 \n\t \
pop %%ecx \n\t \
pop %%ebx \n\t \
pop %%eax" :: "i"(sysc_num), "m"(param), "m"(ret));
ASM "translation" :
Code: Select all
40000390: 55 push %ebp
40000391: 89 e5 mov %esp,%ebp
40000393: 83 ec 20 sub $0x20,%esp
40000396: 8d 45 ec lea -0x14(%ebp),%eax
40000399: 89 45 fc mov %eax,-0x4(%ebp)
4000039c: 8d 45 f8 lea -0x8(%ebp),%eax
4000039f: 89 45 f4 mov %eax,-0xc(%ebp)
400003a2: 50 push %eax
400003a3: 53 push %ebx
400003a4: 51 push %ecx
400003a5: b8 65 00 00 00 mov $0x65,%eax
400003aa: 8b 5d fc mov -0x4(%ebp),%ebx
400003ad: 8b 4d f4 mov -0xc(%ebp),%ecx
400003b0: cd 30 int $0x30
400003b2: 59 pop %ecx
400003b3: 5b pop %ebx
400003b4: 58 pop %eax
400003b5: 31 c0 xor %eax,%eax
400003b7: c9 leave
400003b8: c3 ret
Re: [Newlib] Problem with syscall arguments
Posted: Sun Dec 25, 2011 9:00 am
by Nable
I don't see any problem. Stack frame with parameters (that were passed to fstat) already contains the area that is suitable to be such an array as `params'.
So, compiler eliminates unneeded copy.
To undestand this just look how parameters are passed to function with __cdecl calling convention.
And one more offtopic note: why don't you use EAX for return value (returned by syscall) ?
Because finally it'll be in EAX (return ret) and 'push/pop %%eax' seems.. it seems senseless.
Note2: wow, I finally see the problem. Compiler doesn't understand that value of `ret' can be modified via ret_ptr that was passed via ECX, so it returns 0 every time. Oh, seems that you've broken gcc alias analyser. So, don't do things so complex, make it simple (as i've mentioned in note1) and compiler won't break anything.
Also, may be it wasn't a alias analyser problem, may the problem was that preprocessor didn't replace m(ret) to m(ret_ptr) because symbol `ret' was already defined. Why don't you use inline function instead of #define ?
Re: [Newlib] Problem with syscall arguments
Posted: Sun Dec 25, 2011 9:37 am
by fiveayem
Ok, so that's fine. But why all the parameters passed to my syscall functions are always 0 ? Is it linked to the way I load my ELF binary in memory ? Is it ok if I only load sections of PT_LOAD type ?
Re: [Newlib] Problem with syscall arguments
Posted: Sun Dec 25, 2011 10:23 am
by bluemoon
what's on your kernel side?
a stack switch occurs when switching from ring3 into interrupt handler, do you by any chance looking on the kernel stack?
Re: [Newlib] Problem with syscall arguments
Posted: Sun Dec 25, 2011 10:37 am
by fiveayem
I do not think the problem is related to the stack, I have made sure of it by debugging under Qemu. Currently, my problem is that all parameters passed to my syscall functions seem to be zero and I do not understand why.
EDIT : I fixed the problem by compiling syscalls.c with -O0 flag.
Re: [Newlib] Problem with syscall arguments
Posted: Sun Dec 25, 2011 2:33 pm
by gerryg400
fiveayem wrote:I do not think the problem is related to the stack, I have made sure of it by debugging under Qemu. Currently, my problem is that all parameters passed to my syscall functions seem to be zero and I do not understand why.
EDIT : I fixed the problem by compiling syscalls.c with -O0 flag.
If that's the only change you made you haven't fixed the problem but may have temporarily hidden it. The problem will return.
Re: [Newlib] Problem with syscall arguments
Posted: Mon Dec 26, 2011 3:24 am
by Combuster
the bug is, as previously mentioned, that your syscall as defined never returns a value. It has three inputs but no outputs.