This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
Renesas __trap34() system calls broken - possibly on other platforms, too
- From: "Jonas Mark (ST-FIR/ENG1)" <Mark dot Jonas at de dot bosch dot com>
- To: <newlib at sourceware dot org>
- Cc: "Jonas Mark (ST-FIR/ENG1)" <Mark dot Jonas at de dot bosch dot com>
- Date: Tue, 9 Jan 2007 16:10:16 +0100
- Subject: Renesas __trap34() system calls broken - possibly on other platforms, too
Hello,
I am experiencing problems customizing newlib via __trap34 () on a
little endian, SH3-DSP core using Renesas calling convention. What I can
see is that newlib passes parameters via R4 to R7 while my program
expects to see the variable argument list entirely on the stack.
I am using a precompiled newlib supplied together with a gcc package
from KPIT Cummins (GNUSH-v0603, http://www.kpitgnutools.com). The gcc
identifies itself as "sh-elf-gcc.exe (GCC) 4.2-GNUSH_v0603". The newlib
source code supplied is 1.14.0.
Looking at the problem I realized that at the point where for example
__trap34 (SYS_write, ...) is called there is no prototype declaring
__trap34 () as using a variable parameter list. According to my
experience that leads to the C compiler assuming that __trap34 () has a
fixed parameter list. The result is that __trap34 () parameters are
passed via registers instead of putting them all on the stack.
Sadly, I am locked on a Windows machine so compiling newlib is extremely
painful. It would be very kind if someone could acknowledge this bug and
supply a patch. This is the line that is missing in
libc/sys/sh/syscalls.c and also in libc/sys/sh/truncate.c:
__trap34 (int cmd, ...);
Most likely a very similar problem can be found on other platforms using
a similar system call scheme.
Regards,
Mark Jonas
Further details:
This is the newlib code where __trap34 (SYS_write, ...) is called.
libc/sys/sh/syscalls.c
----------
int
_write ( int file,
char *ptr,
int len)
{
return __trap34 (SYS_write, file, ptr, len);
}
----------
This is the disassembly of the _write() function above. I commented it
to show how the parameters are passed via registers.
sh-elf-objdump -S
c:/KPIT_Cummins/GNUSHv0603-ELF/sh-elf/sh-elf/lib/mrenesas/ml/m2/libc.a
----------
00000270 <__write>:
270: 43 61 mov r4,r1 ; given file
to r1
272: e6 2f mov.l r14,@-r15
274: 53 62 mov r5,r2 ; given ptr
to r2
276: 13 65 mov r1,r5 ; r1 (file)
to r5 (2nd param)
278: 03 d1 mov.l 288 <__write+0x18>,r1 ! 0x0 <__link> ;
r1 = address of __trap34()
27a: 63 67 mov r6,r7 ; given len
to r7 (4th param)
27c: f3 6e mov r15,r14
27e: 04 e4 mov #4,r4 ; SYS_write
to r4 (1st param)
280: 23 66 mov r2,r6 ; r2 (ptr) to
r6 (3rd param)
282: e3 6f mov r14,r15
284: 2b 41 jmp @r1 ; call
__trap34()
286: f6 6e mov.l @r15+,r14
288: 00 00 .word 0x0000
28a: 00 00 .word 0x0000
28c: 09 00 nop
28e: 09 00 nop
----------
This is mixed source and disassembly of my __trap34 () implementation.
You can see that a_code is expected to be on the stack.
----------
// Dummy handler for __trap34 system calls.
// All calls do nothing and return what the application most likely keep
running.
int __trap34(int a_code, ...)
{
290: e6 2f mov.l r14,@-r15
292: f0 7f add #-16,r15
294: f3 6e mov r15,r14
int len = 0;
296: e3 62 mov r14,r2
298: d0 72 add #-48,r2
29a: 00 e1 mov #0,r1
29c: 1d 12 mov.l r1,@(52,r2)
va_list argList;
va_start(argList, a_code);
29e: e3 62 mov r14,r2
2a0: 18 72 add #24,r2
2a2: e3 61 mov r14,r1
2a4: d0 71 add #-48,r1
2a6: 2c 11 mov.l r2,@(48,r1)
switch (a_code)
2a8: e5 50 mov.l @(20,r14),r0
2aa: 04 88 cmp/eq #4,r0
2ac: 01 89 bt 2b2 <___trap34+0x22>
2ae: 27 a0 bra 300 <___trap34+0x70>
2b0: 09 00 nop
{
case SYS_write:
{
// vargs are (int file, char* ptr, int len)
int file = va_arg(argList, int);
2b2: e3 61 mov r14,r1
2b4: d0 71 add #-48,r1
2b6: 1c 53 mov.l @(48,r1),r3
2b8: 33 62 mov r3,r2
2ba: 04 72 add #4,r2
2bc: e3 61 mov r14,r1
2be: d0 71 add #-48,r1
2c0: 2c 11 mov.l r2,@(48,r1)
2c2: 33 61 mov r3,r1
2c4: e3 62 mov r14,r2
2c6: d0 72 add #-48,r2
2c8: 12 61 mov.l @r1,r1
2ca: 1e 12 mov.l r1,@(56,r2)
char *ptr = va_arg(argList, char *);
2cc: e3 61 mov r14,r1
2ce: d0 71 add #-48,r1
2d0: 1c 53 mov.l @(48,r1),r3
2d2: 33 62 mov r3,r2
2d4: 04 72 add #4,r2
2d6: e3 61 mov r14,r1
2d8: d0 71 add #-48,r1
2da: 2c 11 mov.l r2,@(48,r1)
2dc: 33 61 mov r3,r1
2de: e3 62 mov r14,r2
2e0: d0 72 add #-48,r2
2e2: 12 61 mov.l @r1,r1
2e4: 1f 12 mov.l r1,@(60,r2)
len = va_arg(argList, int);
2e6: e3 61 mov r14,r1
2e8: d0 71 add #-48,r1
2ea: 1c 53 mov.l @(48,r1),r3
2ec: 33 62 mov r3,r2
2ee: 04 72 add #4,r2
2f0: e3 61 mov r14,r1
2f2: d0 71 add #-48,r1
2f4: 2c 11 mov.l r2,@(48,r1)
2f6: 33 61 mov r3,r1
2f8: e3 62 mov r14,r2
2fa: d0 72 add #-48,r2
2fc: 12 61 mov.l @r1,r1
2fe: 1d 12 mov.l r1,@(52,r2)
// serial_printn(ptr, len);
}
break;
default:
break;
}
va_end(argList);
return len;
300: e3 61 mov r14,r1
302: d0 71 add #-48,r1
304: 1d 51 mov.l @(52,r1),r1
306: 13 60 mov r1,r0
}
308: 10 7e add #16,r14
30a: e3 6f mov r14,r15
30c: f6 6e mov.l @r15+,r14
30e: 0b 00 rts
310: 09 00 nop
312: 09 00 nop
----------