From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by monty-python.gnu.org with tmda-scanned (Exim 4.24) id 1AM1pF-0001F8-4Z for qemu-devel@nongnu.org; Tue, 18 Nov 2003 04:07:09 -0500 Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.24) id 1AM1oh-0000ru-TI for qemu-devel@nongnu.org; Tue, 18 Nov 2003 04:07:07 -0500 Received: from [62.210.158.41] (helo=moscou.magic.fr) by monty-python.gnu.org with esmtp (Exim 4.24) id 1AM1nf-0000V3-3B for qemu-devel@nongnu.org; Tue, 18 Nov 2003 04:05:31 -0500 Received: from 10.0.0.2 (ppp-181.net-555.magic.fr [62.210.255.181]) by moscou.magic.fr (8.11.6/8.10.1) with ESMTP id hAI843O04497 for ; Tue, 18 Nov 2003 09:04:03 +0100 (CET) Subject: Re: [Qemu-devel] [ADD] tests for PPC target. From: "J. Mayer" In-Reply-To: <1069142555.13659.2265.camel@rapid> References: <20031117105133.7e856e56.Jens.Arm@gmx.de> <1069140512.14646.2174.camel@rapid> <1069142555.13659.2265.camel@rapid> Content-Type: text/plain Message-Id: <1069142927.14646.2274.camel@rapid> Mime-Version: 1.0 Date: 18 Nov 2003 09:08:47 +0100 Content-Transfer-Encoding: 7bit Reply-To: qemu-devel@nongnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org target-ppc__tests__env-test.c.diff Tiny test programs which dumps its environment. diff -urNbB -x CVS qemu-current/target-ppc/tests/env-test.c qemu/target-ppc/tests/env-test.c --- qemu-current/target-ppc/tests/env-test.c Thu Jan 1 01:00:00 1970 +++ qemu/target-ppc/tests/env-test.c Wed Nov 12 10:47:39 2003 @@ -0,0 +1,368 @@ +/* + * This test only wants to dump the stack and environment + * at process start time. This allows to check that qemu env + * is valid, compared to kernel env. + */ + +static const char logfname[] = "/tmp/env-test.log"; +static const char first_mess[] = "Qemu execution environment test\n"; + +#if defined (__i386__) +/* ix86 definitions */ + +register unsigned long __spp __asm__ ("ebp"); + +#define __syscall_return(type, res) \ +do { \ + if ((unsigned long)(res) >= (unsigned long)(-125)) { \ + errno = -(res); \ + res = -1; \ + } \ + return (type) (res); \ +} while (0) + +#define _syscall0(type,name) \ +type name(void) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name)); \ +__syscall_return(type,__res); \ +} + +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1))); \ +__syscall_return(type,__res); \ +} + +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1,type2 arg2) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \ +__syscall_return(type,__res); \ +} + +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1,type2 arg2,type3 arg3) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3))); \ +__syscall_return(type,__res); \ +} + +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3)),"S" ((long)(arg4))); \ +__syscall_return(type,__res); \ +} + +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5))); \ +__syscall_return(type,__res); \ +} + +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \ +{ \ +long __res; \ +__asm__ volatile ("push %%ebp ; movl %%eax,%%ebp ; movl %1,%%eax ; int $0x80 ; pop %%ebp" \ + : "=a" (__res) \ + : "i" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)), \ + "0" ((long)(arg6))); \ +__syscall_return(type,__res); \ +} + +#elif defined (__powerpc__) +/* PowerPC definitions */ + +register unsigned long __spp __asm__ ("r1"); + +#define __syscall_nr(nr, type, name, args...) \ + unsigned long __sc_ret, __sc_err = 0; \ + { \ + register unsigned long __sc_0 __asm__ ("r0"); \ + register unsigned long __sc_3 __asm__ ("r3"); \ + register unsigned long __sc_4 __asm__ ("r4"); \ + register unsigned long __sc_5 __asm__ ("r5"); \ + register unsigned long __sc_6 __asm__ ("r6"); \ + register unsigned long __sc_7 __asm__ ("r7"); \ + \ + __sc_loadargs_##nr(name, args); \ + __asm__ __volatile__ \ + ("sc \n\t" \ + "mfcr %0 " \ + : "=&r" (__sc_0), \ + "=&r" (__sc_3), "=&r" (__sc_4), \ + "=&r" (__sc_5), "=&r" (__sc_6), \ + "=&r" (__sc_7) \ + : __sc_asm_input_##nr \ + : "cr0", "ctr", "memory", \ + "r8", "r9", "r10","r11", "r12"); \ + __sc_ret = __sc_3; \ + } \ + if (__sc_err & 0x10000000) \ + { \ + errno = __sc_ret; \ + __sc_ret = -1; \ + } \ + return (type) __sc_ret + +#define __sc_loadargs_0(name, dummy...) \ + __sc_0 = __NR_##name +#define __sc_loadargs_1(name, arg1) \ + __sc_loadargs_0(name); \ + __sc_3 = (unsigned long) (arg1) +#define __sc_loadargs_2(name, arg1, arg2) \ + __sc_loadargs_1(name, arg1); \ + __sc_4 = (unsigned long) (arg2) +#define __sc_loadargs_3(name, arg1, arg2, arg3) \ + __sc_loadargs_2(name, arg1, arg2); \ + __sc_5 = (unsigned long) (arg3) +#define __sc_loadargs_4(name, arg1, arg2, arg3, arg4) \ + __sc_loadargs_3(name, arg1, arg2, arg3); \ + __sc_6 = (unsigned long) (arg4) +#define __sc_loadargs_5(name, arg1, arg2, arg3, arg4, arg5) \ + __sc_loadargs_4(name, arg1, arg2, arg3, arg4); \ + __sc_7 = (unsigned long) (arg5) + +#define __sc_asm_input_0 "0" (__sc_0) +#define __sc_asm_input_1 __sc_asm_input_0, "1" (__sc_3) +#define __sc_asm_input_2 __sc_asm_input_1, "2" (__sc_4) +#define __sc_asm_input_3 __sc_asm_input_2, "3" (__sc_5) +#define __sc_asm_input_4 __sc_asm_input_3, "4" (__sc_6) +#define __sc_asm_input_5 __sc_asm_input_4, "5" (__sc_7) + +#define _syscall0(type,name) \ +type name(void) \ +{ \ + __syscall_nr(0, type, name); \ +} + +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ + __syscall_nr(1, type, name, arg1); \ +} + +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1, type2 arg2) \ +{ \ + __syscall_nr(2, type, name, arg1, arg2); \ +} + +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1, type2 arg2, type3 arg3) \ +{ \ + __syscall_nr(3, type, name, arg1, arg2, arg3); \ +} + +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ + __syscall_nr(4, type, name, arg1, arg2, arg3, arg4); \ +} + +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ +{ \ + __syscall_nr(5, type, name, arg1, arg2, arg3, arg4, arg5); \ +} +#else +#error "Architecture not supported by now." +#endif + +#define NULL ((void *)0) + +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ + +#define __NR_exit 1 +#define __NR_read 3 +#define __NR_write 4 +#define __NR_open 5 +#define __NR_close 6 +#define __NR_unlink 10 +#define __NR_sync 36 +#define __NR_fsync 118 + +int errno; +unsigned long *__sp; + +_syscall1(void, exit, int, status); +static inline _syscall3(int, read, int, fd, void *, buf, int, count); +static inline _syscall3(int, write, int, fd, const void *, buf, int, count); +static inline _syscall3(int, open, const unsigned char *, pathname, int, flags, int, mode); +static inline _syscall1(int, close, int, fd); +static inline _syscall1(int, unlink, const unsigned char *, pathname); +static inline _syscall0(int, sync); +static inline _syscall1(int, fsync, int, fd); + +static int strlen (const unsigned char *string) +{ + int len; + + for (len = 0; string[len] != '\0'; len++) + continue; + + return len; +} + +static int outstr (int fd, const unsigned char *string, int len) +{ + return write(fd, string, len); +} + +static int outhex (int fd, unsigned long value) +{ + char tmpbuf[9], *pos = tmpbuf; + unsigned long tmp; + int i; + + for (i = 28; i >= 0; i -=4 , pos++) { + tmp = (value >> i) & 0xf; + if (tmp < 0xa) { + *pos = '0' + tmp; + } else { + *pos = ('a' - 10) + tmp; + } + } + *pos = '\0'; + + return write(fd, tmpbuf, 8); +} + +/* We walk through the stack until we reach a page-aligned address */ +static void dump_stack (int fd, int argc, char *const *argv, char *const *envp) +{ + unsigned long sp, *cur; + int i, j; + + __asm__ __volatile__ ("mr %0, 1" : "=r"(sp)); + /* Dump stack, argv and envp pointers */ + outstr(fd, "Stack: ", strlen("Stack: ")); + outhex(fd, sp); + outstr(fd, " ", 1); + outhex(fd, (unsigned long)__sp); + outstr(fd, "\n", 1); + fsync(fd); + cur = __sp - 32; + for (i = 0; ((unsigned long)cur & 0xff0) != 0xff0 && i < 256; i++) { + outhex(fd, (unsigned long)cur); + outstr(fd, ": ", 2); + for (j = 0; j < 4; j++) { + outhex(fd, *cur++); + outstr(fd, " ", 1); + } + outstr(fd, "\n", 1); + } +} + +static void dump_env (int fd, int argc, char *const *argv, char *const *envp) +{ + int i; + + outstr(fd, " argv: ", strlen(" argv: ")); + outhex(fd, (unsigned long)argv); + outstr(fd, " envp: ", strlen(" envp: ")); + outhex(fd, (unsigned long)envp); + outstr(fd, "\n", 1); + /* Dump args and environment */ + outhex(fd, argc); + outstr(fd, " args\n", strlen(" args\n")); + for (i = 0; i < argc; i++) { + outstr(fd, " arg ", 5); + outhex(fd, i); + outstr(fd, " : ", 3); + outstr(fd, argv[i], strlen(argv[i])); + outstr(fd, "\n", 1); + } + outstr(fd, "Env\n", strlen("Env\n")); + for (i = 0; envp[i] != NULL; i++) { + outstr(fd, "envstr ", 7); + outhex(fd, i); + outstr(fd, " : ", 3); + outstr(fd, envp[i], strlen(envp[i])); + outstr(fd, "\n", 1); + } +} + +int main (int argc, char **argv, char **envp) +{ + int logfile; + + unlink(logfname); + logfile = open(logfname, O_WRONLY | O_CREAT, 0644); + if (logfile < 0) + return 1; + sync(); + outstr(logfile, first_mess, strlen(first_mess)); + fsync(logfile); + dump_stack(logfile, argc, argv, envp); + fsync(logfile); + dump_env(logfile, argc, argv, envp); + fsync(logfile); + close(logfile); + + return 0; +} + +/* Here's the program's entry point. + * As one can see, no asm is needed here. + */ +void _start (void) +{ + unsigned long *cur; + unsigned long *__argv, *__envp, __argc; + int __status, i; + + __sp = (unsigned long *)*((unsigned long *)__spp); + cur = __sp; + __argc = *cur; + __argv = cur + 1; + __envp = cur + 2 + __argc; + /* Linux is *STILL* buggy and doesn't respect the API */ + if (*__argv == 0) { + unsigned long tmp = *__envp; + + while (*(unsigned long *)tmp != 0) + tmp--; + tmp += 4; + for (i = 0; i < __argc; i++) { + __argv[i] = (unsigned long)tmp; + while (*(unsigned char *)tmp) + tmp++; + tmp++; + } + } + __status = main(__argc, (char **)__argv, (char **)__envp); + exit(__status); +}