[Newlib] Problem with syscall arguments
[Newlib] Problem with syscall arguments
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.
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
I'm not exactly sure what you mean. Perhaps show a little code...
If a trainstation is where trains stop, what is a workstation ?
Re: [Newlib] Problem with syscall arguments
Paging problem? The array might have a virtual address not corresponding to the physical one seen by the operating system?
Fudge - Simplicity, clarity and speed.
http://github.com/Jezze/fudge/
http://github.com/Jezze/fudge/
Re: [Newlib] Problem with syscall arguments
For instance, let's consider fstat() syscall :
C code :
ASM "translation" :
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));
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
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 ?
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
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
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?
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
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.
EDIT : I fixed the problem by compiling syscalls.c with -O0 flag.
Re: [Newlib] Problem with syscall arguments
If that's the only change you made you haven't fixed the problem but may have temporarily hidden it. The problem will return.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 a trainstation is where trains stop, what is a workstation ?
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: [Newlib] Problem with syscall arguments
the bug is, as previously mentioned, that your syscall as defined never returns a value. It has three inputs but no outputs.