/[gxemul]/upstream/0.4.3/src/useremul.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/0.4.3/src/useremul.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 33 - (show annotations)
Mon Oct 8 16:21:06 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 44149 byte(s)
0.4.3
1 /*
2 * Copyright (C) 2004-2006 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: useremul.c,v 1.72 2006/09/30 05:57:07 debug Exp $
29 *
30 * Userland (syscall) emulation.
31 *
32 * TODO:
33 *
34 * environment passing for most emulation modes
35 *
36 * implement more syscalls
37 *
38 * 32-bit vs 64-bit problems? MIPS n32, o32, n64?
39 *
40 * Dynamic ELFs?
41 *
42 * Try to prefix "/emul/mips/" or similar to all filenames,
43 * and only if that fails, try the given filename.
44 * Read this setting from an environment variable, and only
45 * if there is none, fall back to hardcoded string.
46 *
47 * Automagic errno translation!
48 *
49 * Memory allocation? mmap, munmap, mprotect, etc.
50 * mprotect = unmap in dyntrans...
51 *
52 * File descriptor (0,1,2) assumptions? Find and fix these?
53 *
54 *
55 * This module needs more cleanup.
56 * -------------------------------
57 *
58 *
59 * NOTE: This module (useremul.c) is just a quick hack so far, to see if
60 * userland emulation works at all. It only works for Hello World-
61 * style programs compiled for FreeBSD/alpha or NetBSD/mips.
62 */
63
64 #include <errno.h>
65 #include <fcntl.h>
66 #include <stdio.h>
67 #include <stdlib.h>
68 #include <stdarg.h>
69 #include <string.h>
70 #include <unistd.h>
71 #include <sys/time.h>
72 #include <sys/stat.h>
73 #include <sys/socket.h>
74 #include <sys/resource.h>
75 #include <time.h>
76
77 #include "cpu.h"
78 #include "cpu_mips.h"
79 #include "emul.h"
80 #include "machine.h"
81 #include "memory.h"
82 #include "misc.h"
83 #include "syscall_linux_ppc.h"
84 #include "syscall_netbsd.h"
85 #include "syscall_ultrix.h"
86 #include "sysctl_netbsd.h"
87
88 struct syscall_emul {
89 char *name;
90 int arch;
91 char *cpu_name;
92 void (*f)(struct cpu *, uint32_t);
93 void (*setup)(struct cpu *, int, char **);
94
95 struct syscall_emul *next;
96 };
97
98 static struct syscall_emul *first_syscall_emul;
99
100 /* Max length of strings passed using syscall parameters: */
101 #define MAXLEN 8192
102
103
104 /*
105 * useremul_setup():
106 *
107 * Set up an emulated environment suitable for running userland code. The
108 * program should already have been loaded into memory when this function
109 * is called.
110 */
111 void useremul_setup(struct cpu *cpu, int argc, char **host_argv)
112 {
113 struct syscall_emul *sep;
114
115 sep = first_syscall_emul;
116
117 while (sep != NULL) {
118 if (strcasecmp(cpu->machine->userland_emul, sep->name) == 0) {
119 sep->setup(cpu, argc, host_argv);
120 return;
121 }
122 sep = sep->next;
123 }
124
125 fatal("useremul_setup(): internal error, unimplemented emulation?\n");
126 exit(1);
127 }
128
129
130 /*
131 * useremul__freebsd_setup():
132 *
133 * Set up an emulated userland environment suitable for running FreeBSD
134 * binaries.
135 */
136 void useremul__freebsd_setup(struct cpu *cpu, int argc, char **host_argv)
137 {
138 debug("useremul__freebsd_setup(): TODO\n");
139
140 switch (cpu->machine->arch) {
141 case ARCH_ALPHA:
142 /* According to FreeBSD's /usr/src/lib/csu/alpha/crt1.c: */
143 /* a0 = char **ap */
144 /* a1 = void (*cleanup)(void) from shared loader */
145 /* a2 = struct Struct_Obj_Entry *obj from shared loader */
146 /* a3 = struct ps_strings *ps_strings */
147 cpu->cd.alpha.r[ALPHA_A0] = 0;
148 cpu->cd.alpha.r[ALPHA_A1] = 0;
149 cpu->cd.alpha.r[ALPHA_A2] = 0;
150 cpu->cd.alpha.r[ALPHA_A3] = 0;
151
152 /* What is a good stack pointer? TODO */
153 cpu->cd.alpha.r[ALPHA_SP] = 0x120000000ULL +
154 1048576 * cpu->machine->physical_ram_in_mb - 1024;
155 break;
156 default:
157 fatal("non-Alpha not yet implemented for freebsd emul.\n");
158 exit(1);
159 }
160 }
161
162
163 /*
164 * useremul__linux_setup():
165 *
166 * Set up an emulated userland environment suitable for running Linux
167 * binaries.
168 */
169 void useremul__linux_setup(struct cpu *cpu, int argc, char **host_argv)
170 {
171 debug("useremul__linux_setup(): TODO\n");
172
173 if (cpu->machine->arch != ARCH_PPC) {
174 fatal("non-PPC not yet implemented for linux emul.\n");
175 exit(1);
176 }
177
178 /* What is a good stack pointer? TODO */
179 cpu->cd.ppc.gpr[1] = 0x7ffff000ULL;
180 }
181
182
183 /*
184 * useremul__netbsd_setup():
185 *
186 * Set up an emulated userland environment suitable for running NetBSD
187 * binaries.
188 */
189 void useremul__netbsd_setup(struct cpu *cpu, int argc, char **host_argv)
190 {
191 uint64_t stack_top = 0x7fff0000;
192 uint64_t stacksize = 8 * 1048576;
193 uint64_t stack_margin = 16384;
194 uint64_t cur_argv;
195 int i, i2;
196 int envc = 1;
197
198 switch (cpu->machine->arch) {
199 case ARCH_MIPS:
200 /* See netbsd/sys/src/arch/mips/mips_machdep.c:setregs() */
201 cpu->cd.mips.gpr[MIPS_GPR_A0] = stack_top - stack_margin;
202 cpu->cd.mips.gpr[25] = cpu->pc; /* reg. t9 */
203
204 /* The userland stack: */
205 cpu->cd.mips.gpr[MIPS_GPR_SP] = stack_top - stack_margin;
206 add_symbol_name(&cpu->machine->symbol_context,
207 stack_top - stacksize, stacksize, "userstack", 0, 0);
208
209 /* Stack contents: (TODO: is this correct?) */
210 store_32bit_word(cpu, stack_top - stack_margin, argc);
211
212 cur_argv = stack_top - stack_margin + 128 + (argc + envc)
213 * sizeof(uint32_t);
214 for (i=0; i<argc; i++) {
215 debug("adding argv[%i]: '%s'\n", i, host_argv[i]);
216
217 store_32bit_word(cpu, stack_top - stack_margin +
218 4 + i*sizeof(uint32_t), cur_argv);
219 store_string(cpu, cur_argv, host_argv[i]);
220 cur_argv += strlen(host_argv[i]) + 1;
221 }
222
223 /* Store a NULL value between the args and the environment
224 strings: */
225 store_32bit_word(cpu, stack_top - stack_margin +
226 4 + i*sizeof(uint32_t), 0); i++;
227
228 /* TODO: get environment strings from somewhere */
229
230 /* Store all environment strings: */
231 for (i2 = 0; i2 < envc; i2 ++) {
232 store_32bit_word(cpu, stack_top - stack_margin + 4
233 + (i+i2)*sizeof(uint32_t), cur_argv);
234 store_string(cpu, cur_argv, "DISPLAY=localhost:0.0");
235 cur_argv += strlen("DISPLAY=localhost:0.0") + 1;
236 }
237 break;
238
239 case ARCH_ALPHA:
240 debug("useremul__netbsd_setup(): ALPHA: TODO\n");
241 break;
242
243 case ARCH_ARM:
244 debug("useremul__netbsd_setup(): ARM: TODO\n");
245 break;
246
247 case ARCH_PPC:
248 debug("useremul__netbsd_setup(): PPC: TODO\n");
249
250 /* What is a good stack pointer? TODO */
251 cpu->cd.ppc.gpr[1] = 0x7ffff000ULL;
252
253 break;
254
255 case ARCH_SH:
256 debug("useremul__netbsd_setup(): SH: TODO\n");
257 break;
258
259 case ARCH_X86:
260 debug("useremul__netbsd_setup(): X86: TODO\n");
261
262 break;
263
264 default:
265 fatal("useremul__netbsd_setup(): unimplemented arch\n");
266 exit(1);
267 }
268 }
269
270
271 /*
272 * useremul__ultrix_setup():
273 *
274 * Set up an emulated userland environment suitable for running Ultrix
275 * binaries.
276 */
277 void useremul__ultrix_setup(struct cpu *cpu, int argc, char **host_argv)
278 {
279 uint64_t stack_top = 0x7fff0000;
280 uint64_t stacksize = 8 * 1048576;
281 uint64_t stack_margin = 16384;
282 uint64_t cur_argv;
283 int i, i2;
284 int envc = 1;
285
286 /* TODO: is this correct? */
287 cpu->cd.mips.gpr[MIPS_GPR_A0] = stack_top - stack_margin;
288 cpu->cd.mips.gpr[25] = cpu->pc; /* reg. t9 */
289
290 /* The userland stack: */
291 cpu->cd.mips.gpr[MIPS_GPR_SP] = stack_top - stack_margin;
292 add_symbol_name(&cpu->machine->symbol_context,
293 stack_top - stacksize, stacksize, "userstack", 0, 0);
294
295 /* Stack contents: (TODO: is this correct?) */
296 store_32bit_word(cpu, stack_top - stack_margin, argc);
297
298 cur_argv = stack_top - stack_margin + 128 +
299 (argc + envc) * sizeof(uint32_t);
300 for (i=0; i<argc; i++) {
301 debug("adding argv[%i]: '%s'\n", i, host_argv[i]);
302
303 store_32bit_word(cpu, stack_top - stack_margin +
304 4 + i*sizeof(uint32_t), cur_argv);
305 store_string(cpu, cur_argv, host_argv[i]);
306 cur_argv += strlen(host_argv[i]) + 1;
307 }
308
309 /* Store a NULL value between the args and the environment strings: */
310 store_32bit_word(cpu, stack_top - stack_margin
311 + 4 + i*sizeof(uint32_t), 0); i++;
312
313 /* TODO: get environment strings from somewhere */
314
315 /* Store all environment strings: */
316 for (i2 = 0; i2 < envc; i2 ++) {
317 store_32bit_word(cpu, stack_top - stack_margin + 4 +
318 (i+i2)*sizeof(uint32_t), cur_argv);
319 store_string(cpu, cur_argv, "DISPLAY=localhost:0.0");
320 cur_argv += strlen("DISPLAY=localhost:0.0") + 1;
321 }
322 }
323
324
325 /*
326 * get_userland_string():
327 *
328 * This can be used to retrieve strings, for example filenames,
329 * from the emulated memory.
330 *
331 * NOTE: This function returns a pointer to a malloced buffer. It is up to
332 * the caller to use free().
333 */
334 static unsigned char *get_userland_string(struct cpu *cpu, uint64_t baseaddr)
335 {
336 unsigned char *charbuf;
337 int i, len = 16384;
338
339 charbuf = malloc(len);
340 if (charbuf == NULL) {
341 fprintf(stderr, "get_userland_string(): out of memory (trying"
342 " to allocate %i bytes)\n", len);
343 exit(1);
344 }
345
346 /* TODO: address validity check */
347
348 for (i=0; i<len; i++) {
349 cpu->memory_rw(cpu, cpu->mem, baseaddr+i, charbuf+i,
350 1, MEM_READ, CACHE_DATA);
351 if (charbuf[i] == '\0')
352 break;
353 }
354
355 charbuf[MAXLEN-1] = 0;
356 return charbuf;
357 }
358
359
360 /*
361 * get_userland_buf():
362 *
363 * This can be used to retrieve buffers, for example inet_addr, from
364 * emulated memory.
365 *
366 * NOTE: This function returns a pointer to a malloced buffer. It is up to
367 * the caller to use free().
368 *
369 * TODO: combine this with get_userland_string() in some way
370 */
371 static unsigned char *get_userland_buf(struct cpu *cpu,
372 uint64_t baseaddr, uint64_t len)
373 {
374 unsigned char *charbuf;
375 size_t i;
376
377 charbuf = malloc(len);
378 if (charbuf == NULL) {
379 fprintf(stderr, "get_userland_buf(): out of memory (trying"
380 " to allocate %lli bytes)\n", (long long)len);
381 exit(1);
382 }
383
384 /* TODO: address validity check */
385 for (i=0; i<len; i++) {
386 cpu->memory_rw(cpu, cpu->mem, baseaddr+i, charbuf+i, 1,
387 MEM_READ, CACHE_DATA);
388 /* debug(" %02x", charbuf[i]); */
389 }
390 debug("\n");
391
392 return charbuf;
393 }
394
395
396 /*
397 * useremul_syscall():
398 *
399 * Handle userland syscalls. This function is called whenever a userland
400 * process runs a 'syscall' instruction. The code argument is the code
401 * embedded into the syscall instruction, if any. (This 'code' value is not
402 * necessarily used by specific emulations.)
403 */
404 void useremul_syscall(struct cpu *cpu, uint32_t code)
405 {
406 if (cpu->useremul_syscall == NULL) {
407 fatal("useremul_syscall(): cpu->useremul_syscall == NULL\n");
408 } else
409 cpu->useremul_syscall(cpu, code);
410 }
411
412
413 /*****************************************************************************/
414
415
416 /*
417 * useremul_exit():
418 */
419 int useremul_exit(struct cpu *cpu, uint64_t arg0)
420 {
421 debug("[ exit(%i) ]\n", (int)arg0);
422 cpu->running = 0;
423 cpu->machine->exit_without_entering_debugger = 1;
424 return 0;
425 }
426
427
428 /*
429 * useremul_write():
430 */
431 int64_t useremul_write(struct cpu *cpu, int64_t *errnop,
432 uint64_t arg0, uint64_t arg1, uint64_t arg2)
433 {
434 int64_t res = 0;
435 *errnop = 0;
436 debug("[ write(%i,0x%llx,%lli) ]\n",
437 (int)arg0, (long long)arg1, (long long)arg2);
438 if (arg2 != 0) {
439 unsigned char *cp = get_userland_buf(cpu, arg1, arg2);
440 res = write(arg0, cp, arg2);
441 if (res < 0)
442 *errnop = errno;
443 free(cp);
444 }
445 return res;
446 }
447
448
449 /*
450 * useremul_break():
451 */
452 int64_t useremul_break(struct cpu *cpu, uint64_t arg0)
453 {
454 debug("[ break(0x%llx): TODO ]\n", (long long)arg0);
455
456 /* TODO */
457 return 0;
458 }
459
460
461 /*
462 * useremul_getpid():
463 */
464 int64_t useremul_getpid(struct cpu *cpu)
465 {
466 int64_t pid = getpid();
467 debug("[ getpid(): %lli ]\n", (long long)pid);
468 return pid;
469 }
470
471
472 /*
473 * useremul_getuid():
474 */
475 int64_t useremul_getuid(struct cpu *cpu)
476 {
477 int64_t uid = getuid();
478 debug("[ getuid(): %lli ]\n", (long long)uid);
479 return uid;
480 }
481
482
483 /*
484 * useremul_getegid():
485 */
486 int64_t useremul_getegid(struct cpu *cpu)
487 {
488 int64_t egid = getegid();
489 debug("[ getegid(): %lli ]\n", (long long)egid);
490 return egid;
491 }
492
493
494 /*
495 * useremul_getgid():
496 */
497 int64_t useremul_getgid(struct cpu *cpu)
498 {
499 int64_t gid = getgid();
500 debug("[ getgid(): %lli ]\n", (long long)gid);
501 return gid;
502 }
503
504
505 /*
506 * useremul_sync():
507 */
508 int useremul_sync(struct cpu *cpu)
509 {
510 debug("[ sync() ]\n");
511 sync();
512 return 0;
513 }
514
515
516 /*
517 * useremul_readlink():
518 */
519 int64_t useremul_readlink(struct cpu *cpu, int64_t *errnop,
520 uint64_t arg0, uint64_t arg1, int64_t arg2)
521 {
522 int64_t res = 0;
523 unsigned char *charbuf = get_userland_string(cpu, arg0);
524 unsigned char *buf2;
525
526 debug("[ readlink(\"%s\",0x%llx,%lli) ]\n",
527 charbuf, (long long)arg1, (long long)arg2);
528 if (arg2 == 0 || arg2 > 150000) {
529 fprintf(stderr, "[ useremul_readlink(): TODO ]\n");
530 exit(1);
531 }
532
533 buf2 = malloc(arg2);
534 if (buf2 == NULL) {
535 fprintf(stderr, "[ useremul_readlink(): out of memory ]\n");
536 exit(1);
537 }
538 res = readlink((char *)charbuf, (char *)buf2, arg2);
539 buf2[arg2-1] = '\0';
540 if (res < 0)
541 *errnop = errno;
542 else
543 store_string(cpu, arg1, (char *)buf2);
544 free(buf2);
545 free(charbuf);
546 return res;
547 }
548
549
550 /*
551 * useremul_getrusage():
552 */
553 int64_t useremul_getrusage(struct cpu *cpu, int64_t *errnop,
554 uint64_t arg0, uint64_t arg1)
555 {
556 int64_t res;
557 struct rusage rusage;
558 debug("[ getrusage(%i,0x%llx) ]\n", (int)arg0, (long long)arg1);
559 res = getrusage(arg0, &rusage);
560
561 fatal("TODO: convert rusage into emulated memory!\n");
562 store_64bit_word(cpu, arg1 + 0, rusage.ru_utime.tv_sec);
563 store_64bit_word(cpu, arg1 + 8, rusage.ru_utime.tv_usec);
564 store_64bit_word(cpu, arg1 + 16, rusage.ru_stime.tv_sec);
565 store_64bit_word(cpu, arg1 + 24, rusage.ru_stime.tv_usec);
566
567 return res;
568 }
569
570
571 /*
572 * useremul_fstat():
573 */
574 int64_t useremul_fstat(struct cpu *cpu, int64_t *errnop,
575 int64_t arg0, uint64_t arg1)
576 {
577 int64_t res;
578 struct stat sb;
579 debug("[ fstat(%i,0x%llx) ]\n", (int)arg0, (long long)arg1);
580 res = fstat(arg0, &sb);
581 if (res < 0)
582 *errnop = errno;
583 else {
584 fatal("TODO: convert sb into emulated memory!\n");
585
586 /* NOTE: FreeBSD/alpha only */
587
588 store_32bit_word(cpu, arg1 + 0, sb.st_dev);
589 store_32bit_word(cpu, arg1 + 4, sb.st_ino);
590 /* store_16bit_word(cpu, arg1 + 8, sb.st_mode);
591 */ store_16bit_word(cpu, arg1 + 10, sb.st_nlink);
592 store_32bit_word(cpu, arg1 + 12, sb.st_uid);
593 store_32bit_word(cpu, arg1 + 16, sb.st_gid);
594 store_32bit_word(cpu, arg1 + 20, sb.st_rdev);
595 #if 0
596 store_64bit_word(cpu, arg1 + 24, sb.st_atimespec.tv_sec);
597 store_64bit_word(cpu, arg1 + 32, sb.st_atimespec.tv_nsec);
598 store_64bit_word(cpu, arg1 + 40, sb.st_mtimespec.tv_sec);
599 store_64bit_word(cpu, arg1 + 48, sb.st_mtimespec.tv_nsec);
600 store_64bit_word(cpu, arg1 + 56, sb.st_ctimespec.tv_sec);
601 store_64bit_word(cpu, arg1 + 64, sb.st_ctimespec.tv_nsec);
602
603 store_64bit_word(cpu, arg1 + 72, sb.st_size);
604 store_64bit_word(cpu, arg1 + 80, sb.st_blocks);
605 store_64bit_word(cpu, arg1 + 88, sb.st_blksize);
606 store_64bit_word(cpu, arg1 + 92, sb.st_flags);
607 store_64bit_word(cpu, arg1 + 96, sb.st_gen);
608 #endif
609 }
610 return res;
611 }
612
613
614 /*
615 * useremul_mmap():
616 */
617 int64_t useremul_mmap(struct cpu *cpu, int64_t *errnop,
618 uint64_t arg0, int64_t arg1, int64_t arg2,
619 int64_t arg3, int64_t arg4, uint64_t arg5)
620 {
621 int64_t res = 0;
622
623 /* arg0..5: addr, len, prot, flags, fd, offset */
624 debug("[ mmap(0x%llx,%lli,%i,%i,%i,%lli) ]\n",
625 (long long)arg0, (long long)arg1,
626 (int)arg2, (int)arg3, (int)arg4, (long long)arg5);
627
628 if (arg4 != -1) {
629 fatal("[ useremul_mmap(): fd != -1: TODO ]\n");
630 cpu->running = 0;
631 return 0;
632 }
633
634 /* Anonymous allocation. */
635 if (arg0 != 0) {
636 fatal("[ useremul_mmap(): addr != 0: TODO ]\n");
637 cpu->running = 0;
638 return 0;
639 }
640
641 fatal("[ useremul_mmap(): TODO ]\n");
642
643 res = 0x18000000ULL;
644
645 return res;
646 }
647
648
649 /*****************************************************************************/
650
651
652 /*
653 * useremul__freebsd():
654 *
655 * FreeBSD/Alpha syscall emulation.
656 *
657 * TODO: How to make this work nicely with non-Alpha archs.
658 */
659 static void useremul__freebsd(struct cpu *cpu, uint32_t code)
660 {
661 int nr;
662 int64_t res = 0, err = 0;
663 uint64_t arg0, arg1, arg2, arg3, arg4, arg5;
664
665 nr = cpu->cd.alpha.r[ALPHA_V0];
666 arg0 = cpu->cd.alpha.r[ALPHA_A0];
667 arg1 = cpu->cd.alpha.r[ALPHA_A1];
668 arg2 = cpu->cd.alpha.r[ALPHA_A2];
669 arg3 = cpu->cd.alpha.r[ALPHA_A3];
670 arg4 = cpu->cd.alpha.r[ALPHA_A4];
671 arg5 = cpu->cd.alpha.r[ALPHA_A5];
672
673 if (nr == 198) {
674 /* ___syscall */
675 nr = arg0;
676 arg0 = arg1;
677 arg1 = arg2;
678 arg2 = arg3;
679 arg3 = arg4;
680 arg4 = arg5;
681 /* TODO: stack arguments */
682 }
683
684 switch (nr) {
685
686 case 1: res = useremul_exit(cpu, arg0);
687 break;
688
689 case 4: res = useremul_write(cpu, &err, arg0, arg1, arg2);
690 break;
691
692 case 17:res = useremul_break(cpu, arg0);
693 break;
694
695 case 20:res = useremul_getpid(cpu);
696 break;
697
698 case 24:res = useremul_getuid(cpu);
699 break;
700
701 case 43:res = useremul_getegid(cpu);
702 break;
703
704 case 47:res = useremul_getgid(cpu);
705 break;
706
707 case 58:res = useremul_readlink(cpu, &err, arg0, arg1, arg2);
708 break;
709
710 case 73:/* munmap. TODO */
711 res = 1;
712 break;
713
714 case 117:res = useremul_getrusage(cpu, &err, arg0, arg1);
715 break;
716
717 case 189:res = useremul_fstat(cpu, &err, arg0, arg1);
718 break;
719
720 case 197:res = useremul_mmap(cpu, &err, arg0, arg1, arg2, arg3,
721 arg4, arg5);
722 break;
723
724 default:fatal("useremul__freebsd(): syscall %i not yet "
725 "implemented\n", nr);
726 cpu->running = 0;
727 }
728
729 if (err) {
730 cpu->cd.alpha.r[ALPHA_A3] = 1;
731 cpu->cd.alpha.r[ALPHA_V0] = err;
732 } else {
733 cpu->cd.alpha.r[ALPHA_A3] = 0;
734 cpu->cd.alpha.r[ALPHA_V0] = res;
735 }
736 }
737
738
739 /*
740 * useremul__linux():
741 *
742 * Linux syscall emulation.
743 *
744 * TODO: How to make this work nicely with non-PPC archs.
745 */
746 static void useremul__linux(struct cpu *cpu, uint32_t code)
747 {
748 int nr;
749 int64_t res = 0, err = 0;
750 uint64_t arg0, arg1, arg2, arg3;
751
752 if (code != 0) {
753 fatal("useremul__linux(): code %i: TODO\n", (int)code);
754 exit(1);
755 }
756
757 nr = cpu->cd.ppc.gpr[0];
758 arg0 = cpu->cd.ppc.gpr[3];
759 arg1 = cpu->cd.ppc.gpr[4];
760 arg2 = cpu->cd.ppc.gpr[5];
761 arg3 = cpu->cd.ppc.gpr[6];
762
763 switch (nr) {
764
765 case LINUX_PPC_SYS_exit:
766 res = useremul_exit(cpu, arg0);
767 break;
768
769 case LINUX_PPC_SYS_write:
770 res = useremul_write(cpu, &err, arg0, arg1, arg2);
771 break;
772
773 default:
774 fatal("useremul__linux(): syscall %i not yet implemented\n",
775 nr);
776 cpu->running = 0;
777 }
778
779 /* return res: TODO */
780 }
781
782
783 /*
784 * useremul__netbsd():
785 *
786 * NetBSD syscall emulation.
787 */
788 static void useremul__netbsd(struct cpu *cpu, uint32_t code)
789 {
790 int error_flag = 0, result_high_set = 0;
791 uint64_t arg0=0,arg1=0,arg2=0,arg3=0,stack0=0,stack1=0,stack2=0;
792 int sysnr = 0;
793 int64_t error_code = 0;
794 uint64_t result_low = 0;
795 uint64_t result_high = 0;
796 struct timeval tv;
797 struct timezone tz;
798 int descr;
799 uint64_t length, mipsbuf, flags;
800 unsigned char *charbuf;
801 uint32_t sysctl_name, sysctl_namelen, sysctl_oldp,
802 sysctl_oldlenp, sysctl_newp, sysctl_newlen;
803 uint32_t name0, name1, name2, name3;
804
805 switch (cpu->machine->arch) {
806 case ARCH_MIPS:
807 sysnr = cpu->cd.mips.gpr[MIPS_GPR_V0];
808 if (sysnr == NETBSD_SYS___syscall) {
809 sysnr = cpu->cd.mips.gpr[MIPS_GPR_A0] +
810 (cpu->cd.mips.gpr[MIPS_GPR_A1] << 32);
811 arg0 = cpu->cd.mips.gpr[MIPS_GPR_A2];
812 arg1 = cpu->cd.mips.gpr[MIPS_GPR_A3];
813 /* TODO: stack arguments? Are these correct? */
814 arg2 = load_32bit_word(cpu,
815 cpu->cd.mips.gpr[MIPS_GPR_SP] + 8);
816 arg3 = load_32bit_word(cpu,
817 cpu->cd.mips.gpr[MIPS_GPR_SP] + 16);
818 stack0 = load_32bit_word(cpu,
819 cpu->cd.mips.gpr[MIPS_GPR_SP] + 24);
820 stack1 = load_32bit_word(cpu,
821 cpu->cd.mips.gpr[MIPS_GPR_SP] + 32);
822 stack2 = load_32bit_word(cpu,
823 cpu->cd.mips.gpr[MIPS_GPR_SP] + 40);
824 } else {
825 arg0 = cpu->cd.mips.gpr[MIPS_GPR_A0];
826 arg1 = cpu->cd.mips.gpr[MIPS_GPR_A1];
827 arg2 = cpu->cd.mips.gpr[MIPS_GPR_A2];
828 arg3 = cpu->cd.mips.gpr[MIPS_GPR_A3];
829 /* TODO: stack arguments? Are these correct? */
830 stack0 = load_32bit_word(cpu,
831 cpu->cd.mips.gpr[MIPS_GPR_SP] + 4);
832 stack1 = load_32bit_word(cpu,
833 cpu->cd.mips.gpr[MIPS_GPR_SP] + 8);
834 stack2 = load_32bit_word(cpu,
835 cpu->cd.mips.gpr[MIPS_GPR_SP] + 12);
836 }
837 break;
838
839 case ARCH_PPC:
840 sysnr = cpu->cd.ppc.gpr[0];
841 arg0 = cpu->cd.ppc.gpr[3];
842 arg1 = cpu->cd.ppc.gpr[4];
843 arg2 = cpu->cd.ppc.gpr[5];
844 arg3 = cpu->cd.ppc.gpr[6];
845 /* TODO: More arguments? Stack arguments? */
846 break;
847
848 case ARCH_ARM:
849 sysnr = code & 0xfffff;
850 arg0 = cpu->cd.arm.r[0];
851 arg1 = cpu->cd.arm.r[1];
852 arg2 = cpu->cd.arm.r[2];
853 arg3 = cpu->cd.arm.r[3];
854 /* TODO: More arguments? Stack arguments? */
855 break;
856
857 default:fatal("netbsd syscall for this arch: TODO\n");
858 exit(1);
859 }
860
861 /*
862 * NOTE/TODO: The following code should not be CPU arch dependent!
863 */
864
865 switch (sysnr) {
866
867 case NETBSD_SYS_exit:
868 debug("[ exit(%i) ]\n", (int)arg0);
869 cpu->running = 0;
870 cpu->machine->exit_without_entering_debugger = 1;
871 break;
872
873 case NETBSD_SYS_read:
874 debug("[ read(%i,0x%llx,%lli) ]\n",
875 (int)arg0, (long long)arg1, (long long)arg2);
876
877 if (arg2 != 0) {
878 charbuf = malloc(arg2);
879 if (charbuf == NULL) {
880 fprintf(stderr, "out of memory in "
881 "useremul__netbsd()\n");
882 exit(1);
883 }
884 result_low = read(arg0, charbuf, arg2);
885 if ((int64_t)result_low < 0) {
886 error_code = errno;
887 error_flag = 1;
888 }
889
890 /* TODO: address validity check */
891 cpu->memory_rw(cpu, cpu->mem, arg1, charbuf,
892 arg2, MEM_WRITE, CACHE_DATA);
893 free(charbuf);
894 }
895 break;
896
897 case NETBSD_SYS_write:
898 descr = arg0;
899 mipsbuf = arg1;
900 length = arg2;
901 debug("[ write(%i,0x%llx,%lli) ]\n",
902 (int)descr, (long long)mipsbuf, (long long)length);
903 if (length != 0) {
904 charbuf = malloc(length);
905 if (charbuf == NULL) {
906 fprintf(stderr, "out of memory in "
907 "useremul__netbsd()\n");
908 exit(1);
909 }
910 /* TODO: address validity check */
911 cpu->memory_rw(cpu, cpu->mem, mipsbuf, charbuf,
912 length, MEM_READ, CACHE_DATA);
913 result_low = write(descr, charbuf, length);
914 if ((int64_t)result_low < 0) {
915 error_code = errno;
916 error_flag = 1;
917 }
918 free(charbuf);
919 }
920 break;
921
922 case NETBSD_SYS_open:
923 charbuf = get_userland_string(cpu, arg0);
924 debug("[ open(\"%s\", 0x%llx, 0x%llx) ]\n",
925 charbuf, (long long)arg1, (long long)arg2);
926 result_low = open((char *)charbuf, arg1, arg2);
927 if ((int64_t)result_low < 0) {
928 error_flag = 1;
929 error_code = errno;
930 }
931 free(charbuf);
932 break;
933
934 case NETBSD_SYS_close:
935 descr = arg0;
936 debug("[ close(%i) ]\n", (int)descr);
937 error_code = close(descr);
938 if (error_code != 0)
939 error_flag = 1;
940 break;
941
942 case NETBSD_SYS_access:
943 charbuf = get_userland_string(cpu, arg0);
944 debug("[ access(\"%s\", 0x%llx) ]\n",
945 charbuf, (long long) arg1);
946 result_low = access((char *)charbuf, arg1);
947 if (result_low != 0) {
948 error_flag = 1;
949 error_code = errno;
950 }
951 free(charbuf);
952 break;
953
954 case NETBSD_SYS_getuid:
955 result_low = useremul_getuid(cpu);
956 break;
957
958 case NETBSD_SYS_geteuid:
959 debug("[ geteuid() ]\n");
960 result_low = geteuid();
961 break;
962
963 case NETBSD_SYS_getgid:
964 debug("[ getgid() ]\n");
965 result_low = getgid();
966 break;
967
968 case NETBSD_SYS_getegid:
969 debug("[ getegid() ]\n");
970 result_low = getegid();
971 break;
972
973 case NETBSD_SYS_getfsstat:
974 mipsbuf = arg0;
975 length = arg1;
976 flags = arg2;
977 debug("[ getfsstat(0x%llx,%lli,0x%llx) ]\n",
978 (long long)mipsbuf, (long long)length,
979 (long long)flags);
980
981 result_low = 0; /* nr of mounted filesystems,
982 for now (TODO) */
983
984 /* Fill in the struct statfs buffer at arg0...
985 copy data from the host's getfsstat(). TODO */
986 #if 1
987 result_low = 1;
988 store_32bit_word(cpu, mipsbuf + 0, 0); /* f_spare2 */
989 store_32bit_word(cpu, mipsbuf + 4, 1024); /* f_bsize */
990 store_32bit_word(cpu, mipsbuf + 8, 65536); /* f_iosize */
991 store_32bit_word(cpu, mipsbuf + 12, 100); /* f_blocks */
992 store_32bit_word(cpu, mipsbuf + 16, 50); /* f_bfree */
993 store_32bit_word(cpu, mipsbuf + 20, 10); /* f_bavail */
994 store_32bit_word(cpu, mipsbuf + 24, 50); /* f_files */
995 store_32bit_word(cpu, mipsbuf + 28, 25); /* f_ffree */
996 store_32bit_word(cpu, mipsbuf + 28, 0x1234); /* f_fsid */
997 store_32bit_word(cpu, mipsbuf + 32, 0); /* f_owner */
998 store_32bit_word(cpu, mipsbuf + 36, 0); /* f_type */
999 store_32bit_word(cpu, mipsbuf + 40, 0); /* f_flags */
1000 store_32bit_word(cpu, mipsbuf + 44, 0); /* f_fspare[0] */
1001 store_32bit_word(cpu, mipsbuf + 48, 0); /* f_fspare[1] */
1002 store_string(cpu, mipsbuf + 52, "ffs"); /* f_typename */
1003 #define MFSNAMELEN 16
1004 #define MNAMELEN 90
1005 store_string(cpu, mipsbuf + 52 + MFSNAMELEN, "/");
1006 /* f_mntonname */
1007 store_string(cpu, mipsbuf + 52 + MFSNAMELEN + MNAMELEN, "ffs");
1008 /* f_mntfromname */
1009 #endif
1010 break;
1011
1012 case NETBSD_SYS_break:
1013 useremul_break(cpu, arg0);
1014 break;
1015
1016 case NETBSD_SYS_readlink:
1017 result_low = useremul_readlink(cpu, &error_code,
1018 arg0, arg1, arg2);
1019 break;
1020
1021 case NETBSD_SYS_sync:
1022 useremul_sync(cpu);
1023 break;
1024
1025 case NETBSD_SYS_gettimeofday:
1026 debug("[ gettimeofday(0x%llx,0x%llx) ]\n",
1027 (long long)arg0, (long long)arg1);
1028 result_low = gettimeofday(&tv, &tz);
1029 if (result_low) {
1030 error_flag = 1;
1031 error_code = errno;
1032 } else {
1033 if (arg0 != 0) {
1034 /* Store tv.tv_sec and tv.tv_usec as
1035 'long' (32-bit) values: */
1036 store_32bit_word(cpu, arg0 + 0,
1037 tv.tv_sec);
1038 store_32bit_word(cpu, arg0 + 4,
1039 tv.tv_usec);
1040 }
1041 if (arg1 != 0) {
1042 /* Store tz.tz_minuteswest and
1043 tz.tz_dsttime as 'long'
1044 (32-bit) values: */
1045 store_32bit_word(cpu, arg1 + 0,
1046 tz.tz_minuteswest);
1047 store_32bit_word(cpu, arg1 + 4,
1048 tz.tz_dsttime);
1049 }
1050 }
1051 break;
1052
1053 case NETBSD_SYS_mmap:
1054 debug("[ mmap(0x%x,%i,%i,%i,%i,0x%llx): TODO ]\n",
1055 arg0, arg1, arg2, arg3, stack0, (long long)stack1);
1056
1057 if ((int32_t)stack0 == -1) {
1058 /*
1059 * Anonymous allocation:
1060 *
1061 * TODO: Fix this!!!
1062 *
1063 * This quick hack simply allocates anonymous
1064 * mmap memory approximately below the stack.
1065 * This will probably not work with dynamically
1066 * loaded libraries and such.
1067 */
1068 static uint32_t mmap_anon_ptr = 0x70000000;
1069 mmap_anon_ptr -= arg1;
1070 /* round down to page boundary: */
1071 mmap_anon_ptr &= ~4095;
1072 debug("ANON: %i bytes at 0x%08x (TODO: not "
1073 "working yet?)\n", (int)arg1,
1074 mmap_anon_ptr);
1075 result_low = mmap_anon_ptr;
1076 } else {
1077 /* Return NULL for now */
1078 }
1079 break;
1080
1081 case NETBSD_SYS_dup:
1082 debug("[ dup(%i) ]\n", (int)arg0);
1083 result_low = dup(arg0);
1084 if ((int64_t)result_low < 0) {
1085 error_code = errno;
1086 error_flag = 1;
1087 }
1088 break;
1089
1090 case NETBSD_SYS_socket:
1091 debug("[ socket(%i,%i,%i) ]\n",
1092 (int)arg0, (int)arg1, (int)arg2);
1093 result_low = socket(arg0,arg1,arg2);
1094 if ((int64_t)result_low < 0) {
1095 error_code = errno;
1096 error_flag = 1;
1097 }
1098 break;
1099
1100 case NETBSD_SYS_issetugid:
1101 debug("[ issetugid() ]\n");
1102 /* TODO: actually call the real issetugid? */
1103 break;
1104
1105 case NETBSD_SYS_nanosleep:
1106 debug("[ nanosleep(0x%llx,0x%llx) ]\n",
1107 (long long)arg0, (long long)arg1);
1108
1109 if (arg0 != 0) {
1110 uint32_t sec = load_32bit_word(cpu, arg0 + 0);
1111 uint32_t nsec = load_32bit_word(cpu, arg0 + 4);
1112 struct timespec ts;
1113 ts.tv_sec = sec;
1114 ts.tv_nsec = nsec;
1115 result_low = nanosleep(&ts, NULL);
1116 if (result_low)
1117 fprintf(stderr, "netbsd emulation "
1118 "nanosleep() failed\n");
1119 /* TODO: arg1 */
1120 } else {
1121 error_flag = 1;
1122 error_code = 14; /* EFAULT */
1123 }
1124 break;
1125
1126 case NETBSD_SYS___fstat13:
1127 debug("[ __fstat13(%lli,0x%llx): TODO ]\n",
1128 (long long)arg0, (long long)arg1);
1129 error_flag = 1;
1130 error_code = 9; /* EBADF */
1131 break;
1132
1133 case NETBSD_SYS___getcwd:
1134 debug("[ __getcwd(0x%llx,%lli): TODO ]\n",
1135 (long long)arg0, (long long)arg1);
1136 if (arg1 != 0 && arg1 < 500000) {
1137 char *buf = malloc(arg1);
1138 unsigned int i;
1139
1140 getcwd(buf, arg1);
1141
1142 /* zero-terminate in host's space: */
1143 buf[arg1 - 1] = 0;
1144
1145 for (i = 0; i<arg1 && i < arg1; i++)
1146 cpu->memory_rw(cpu, cpu->mem, arg0 + i,
1147 (unsigned char *)&buf[i], 1,
1148 MEM_WRITE, CACHE_NONE);
1149
1150 /* zero-terminate in emulated space: */
1151 cpu->memory_rw(cpu, cpu->mem, arg0 + arg1-1,
1152 (unsigned char *)&buf[arg1 - 1],
1153 1, MEM_WRITE, CACHE_NONE);
1154
1155 free(buf);
1156 }
1157 result_low = arg0;
1158 break;
1159
1160 case NETBSD_SYS___sigaction14:
1161 debug("[ __sigaction14(%lli,0x%llx,0x%llx): TODO ]\n",
1162 (long long)arg0, (long long)arg1, (long long)arg2);
1163 error_flag = 1;
1164 error_code = 9; /* EBADF */
1165 break;
1166
1167 case NETBSD_SYS___sysctl:
1168 sysctl_name = arg0;
1169 sysctl_namelen = arg1;
1170 sysctl_oldp = arg2;
1171 sysctl_oldlenp = arg3;
1172 sysctl_newp = load_32bit_word(cpu,
1173 cpu->cd.mips.gpr[MIPS_GPR_SP]);
1174 /* TODO: +4 and +8 ?? */
1175 sysctl_newlen = load_32bit_word(cpu,
1176 cpu->cd.mips.gpr[MIPS_GPR_SP] + 4);
1177 debug("[ __sysctl(");
1178
1179 name0 = load_32bit_word(cpu, sysctl_name + 0);
1180 name1 = load_32bit_word(cpu, sysctl_name + 4);
1181 name2 = load_32bit_word(cpu, sysctl_name + 8);
1182 name3 = load_32bit_word(cpu, sysctl_name + 12);
1183 debug("name (@ 0x%08x) = %i, %i, %i, %i) ]\n",
1184 sysctl_name, name0, name1, name2, name3);
1185
1186 if (name0 == CTL_KERN && name1 == KERN_HOSTNAME) {
1187 char hname[256];
1188 hname[0] = '\0';
1189 gethostname(hname, sizeof(hname));
1190 hname[sizeof(hname)-1] = '\0';
1191 if (sysctl_oldp != 0)
1192 store_string(cpu, sysctl_oldp, hname);
1193 if (sysctl_oldlenp != 0)
1194 store_32bit_word(cpu, sysctl_oldlenp,
1195 strlen(hname));
1196 } else if (name0 == CTL_HW && name1 == HW_PAGESIZE) {
1197 if (sysctl_oldp != 0)
1198 store_32bit_word(cpu,
1199 sysctl_oldp, 4096);
1200 if (sysctl_oldlenp != 0)
1201 store_32bit_word(cpu,
1202 sysctl_oldlenp, sizeof(uint32_t));
1203 } else {
1204 error_flag = 1;
1205 error_code = 2; /* ENOENT */
1206 }
1207 break;
1208
1209 default:
1210 fatal("[ UNIMPLEMENTED netbsd syscall %i ]\n", sysnr);
1211 error_flag = 1;
1212 error_code = 78; /* ENOSYS */
1213 }
1214
1215
1216 switch (cpu->machine->arch) {
1217 case ARCH_ARM:
1218 /* NetBSD/arm return values: */
1219 cpu->cd.arm.r[0] = result_low;
1220 cpu->cd.arm.cpsr &= ~ARM_FLAG_C;
1221 if (error_flag) {
1222 cpu->cd.arm.cpsr |= ARM_FLAG_C;
1223 cpu->cd.arm.r[0] = error_code;
1224 }
1225 if (result_high_set)
1226 cpu->cd.arm.r[1] = result_high;
1227 cpu->cd.arm.flags = cpu->cd.arm.cpsr >> 28;
1228 break;
1229 case ARCH_MIPS:
1230 /*
1231 * NetBSD/mips return values:
1232 *
1233 * a3 is 0 if the syscall was ok, otherwise 1.
1234 * v0 (and sometimes v1) contain the result value.
1235 */
1236 cpu->cd.mips.gpr[MIPS_GPR_A3] = error_flag;
1237 if (error_flag)
1238 cpu->cd.mips.gpr[MIPS_GPR_V0] = error_code;
1239 else
1240 cpu->cd.mips.gpr[MIPS_GPR_V0] = result_low;
1241
1242 if (result_high_set)
1243 cpu->cd.mips.gpr[MIPS_GPR_V1] = result_high;
1244 break;
1245 case ARCH_PPC:
1246 /*
1247 * NetBSD/powerpc return values:
1248 *
1249 * TODO
1250 */
1251 cpu->cd.ppc.gpr[3] = result_low;
1252
1253 if (result_high_set)
1254 cpu->cd.ppc.gpr[4] = result_high;
1255 break;
1256 }
1257 }
1258
1259
1260 /*
1261 * useremul__ultrix():
1262 *
1263 * Ultrix syscall emulation.
1264 */
1265 static void useremul__ultrix(struct cpu *cpu, uint32_t code)
1266 {
1267 int error_flag = 0, result_high_set = 0;
1268 uint64_t arg0,arg1,arg2,arg3,stack0=0,stack1=0,stack2;
1269 int sysnr = 0;
1270 int64_t error_code = 0;
1271 uint64_t result_low = 0;
1272 uint64_t result_high = 0;
1273 struct timeval tv;
1274 struct timezone tz;
1275 int descr;
1276 uint64_t length, mipsbuf;
1277 unsigned char *charbuf;
1278
1279 /*
1280 * Ultrix/pmax gets the syscall number in register v0,
1281 * and syscall arguments in registers a0, a1, ...
1282 *
1283 * TODO: If there is a __syscall-like syscall (as in NetBSD)
1284 * then 64-bit args may be passed in two registers or something...
1285 * If so, then copy from the section above (NetBSD).
1286 */
1287 sysnr = cpu->cd.mips.gpr[MIPS_GPR_V0];
1288
1289 arg0 = cpu->cd.mips.gpr[MIPS_GPR_A0];
1290 arg1 = cpu->cd.mips.gpr[MIPS_GPR_A1];
1291 arg2 = cpu->cd.mips.gpr[MIPS_GPR_A2];
1292 arg3 = cpu->cd.mips.gpr[MIPS_GPR_A3];
1293 /* TODO: stack arguments? Are these correct? */
1294 stack0 = load_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_SP] + 0);
1295 stack1 = load_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_SP] + 4);
1296 stack2 = load_32bit_word(cpu, cpu->cd.mips.gpr[MIPS_GPR_SP] + 8);
1297
1298 switch (sysnr) {
1299
1300 case ULTRIX_SYS_exit:
1301 debug("[ exit(%i) ]\n", (int)arg0);
1302 cpu->running = 0;
1303 cpu->machine->exit_without_entering_debugger = 1;
1304 break;
1305
1306 case ULTRIX_SYS_read:
1307 debug("[ read(%i,0x%llx,%lli) ]\n",
1308 (int)arg0, (long long)arg1, (long long)arg2);
1309
1310 if (arg2 != 0) {
1311 charbuf = malloc(arg2);
1312 if (charbuf == NULL) {
1313 fprintf(stderr, "out of memory in "
1314 "useremul__ultrix()\n");
1315 exit(1);
1316 }
1317
1318 result_low = read(arg0, charbuf, arg2);
1319 if ((int64_t)result_low < 0) {
1320 error_code = errno;
1321 error_flag = 1;
1322 }
1323
1324 /* TODO: address validity check */
1325 cpu->memory_rw(cpu, cpu->mem, arg1, charbuf,
1326 arg2, MEM_WRITE, CACHE_DATA);
1327
1328 free(charbuf);
1329 }
1330 break;
1331
1332 case ULTRIX_SYS_write:
1333 descr = arg0;
1334 mipsbuf = arg1;
1335 length = arg2;
1336 debug("[ write(%i,0x%llx,%lli) ]\n",
1337 (int)descr, (long long)mipsbuf, (long long)length);
1338
1339 if (length != 0) {
1340 charbuf = malloc(length);
1341 if (charbuf == NULL) {
1342 fprintf(stderr, "out of memory in "
1343 "useremul__ultrix()\n");
1344 exit(1);
1345 }
1346
1347 /* TODO: address validity check */
1348 cpu->memory_rw(cpu, cpu->mem, mipsbuf, charbuf,
1349 length, MEM_READ, CACHE_DATA);
1350
1351 result_low = write(descr, charbuf, length);
1352 if ((int64_t)result_low < 0) {
1353 error_code = errno;
1354 error_flag = 1;
1355 }
1356 free(charbuf);
1357 }
1358 break;
1359
1360 case ULTRIX_SYS_open:
1361 charbuf = get_userland_string(cpu, arg0);
1362 debug("[ open(\"%s\", 0x%llx, 0x%llx) ]\n",
1363 charbuf, (long long)arg1, (long long)arg2);
1364
1365 result_low = open((char *)charbuf, arg1, arg2);
1366 if ((int64_t)result_low < 0) {
1367 error_flag = 1;
1368 error_code = errno;
1369 }
1370 free(charbuf);
1371 break;
1372
1373 case ULTRIX_SYS_close:
1374 descr = arg0;
1375 debug("[ close(%i) ]\n", (int)descr);
1376
1377 /* Special case because some Ultrix programs tend
1378 to close low descriptors: */
1379 if (descr <= 2) {
1380 error_flag = 1;
1381 error_code = 2; /* TODO: Ultrix ENOENT error code */
1382 break;
1383 }
1384
1385 error_code = close(descr);
1386 if (error_code != 0)
1387 error_flag = 1;
1388 break;
1389
1390 case ULTRIX_SYS_break:
1391 useremul_break(cpu, arg0);
1392 break;
1393
1394 case ULTRIX_SYS_sync:
1395 useremul_sync(cpu);
1396 break;
1397
1398 case ULTRIX_SYS_getuid:
1399 result_low = useremul_getuid(cpu);
1400 break;
1401
1402 case ULTRIX_SYS_getgid:
1403 debug("[ getgid() ]\n");
1404 result_low = getgid();
1405 break;
1406
1407 case ULTRIX_SYS_dup:
1408 debug("[ dup(%i) ]\n", (int)arg0);
1409 result_low = dup(arg0);
1410 if ((int64_t)result_low < 0) {
1411 error_code = errno;
1412 error_flag = 1;
1413 }
1414 break;
1415
1416 case ULTRIX_SYS_socket:
1417 debug("[ socket(%i,%i,%i) ]\n",
1418 (int)arg0, (int)arg1, (int)arg2);
1419 result_low = socket(arg0,arg1,arg2);
1420 if ((int64_t)result_low < 0) {
1421 error_code = errno;
1422 error_flag = 1;
1423 }
1424 break;
1425
1426 case ULTRIX_SYS_select:
1427 debug("[ select(%i,0x%x,0x%x,0x%x,0x%x): TODO ]\n",
1428 (int)arg0, (int)arg1, (int)arg2, (int)arg3, (int)stack0);
1429
1430 /* TODO */
1431 {
1432 fd_set fdset;
1433 FD_SET(3, &fdset);
1434 result_low = select(4, &fdset, NULL, NULL, NULL);
1435 }
1436 break;
1437
1438 case ULTRIX_SYS_setsockopt:
1439 debug("[ setsockopt(%i,%i,%i,0x%x,%i): TODO ]\n",
1440 (int)arg0, (int)arg1, (int)arg2, (int)arg3, (int)stack0);
1441 /* TODO: len is not 4, len is stack0? */
1442 charbuf = get_userland_buf(cpu, arg3, 4);
1443 /* TODO: endianness of charbuf, etc */
1444 result_low = setsockopt(arg0, arg1, arg2, (void *)charbuf, 4);
1445 if ((int64_t)result_low < 0) {
1446 error_code = errno;
1447 error_flag = 1;
1448 }
1449 free(charbuf);
1450 printf("setsockopt!!!! res = %i error=%i\n",
1451 (int)result_low, (int)error_code);
1452 break;
1453
1454 case ULTRIX_SYS_connect:
1455 debug("[ connect(%i,0x%x,%i) ]\n",
1456 (int)arg0, (int)arg1, (int)arg2);
1457 charbuf = get_userland_buf(cpu, arg1, arg2);
1458 result_low = connect(arg0, (void *)charbuf, arg2);
1459 if ((int64_t)result_low < 0) {
1460 error_code = errno;
1461 error_flag = 1;
1462 }
1463 printf("connect!!!! res = %i error=%i\n",
1464 (int)result_low, (int)error_code);
1465 free(charbuf);
1466 break;
1467
1468 case ULTRIX_SYS_fcntl:
1469 debug("[ fcntl(%i,%i,0x%x): TODO ]\n",
1470 (int)arg0, (int)arg1, (int)arg2);
1471 /* TODO: how about that third argument? */
1472 result_low = fcntl(arg0, arg1, arg2);
1473 if ((int64_t)result_low < 0) {
1474 error_code = errno;
1475 error_flag = 1;
1476 }
1477 printf("fcntl!!!! res = %i error=%i\n",
1478 (int)result_low, (int)error_code);
1479 break;
1480
1481 case ULTRIX_SYS_stat43:
1482 charbuf = get_userland_string(cpu, arg0);
1483 debug("[ stat(\"%s\", 0x%llx): TODO ]\n",
1484 charbuf, (long long)arg1);
1485
1486 if (arg1 != 0) {
1487 struct stat st;
1488 result_low = stat((char *)charbuf, &st);
1489 if ((int64_t)result_low < 0) {
1490 error_flag = 1;
1491 error_code = errno;
1492 } else {
1493 /* Fill in the Ultrix stat struct at arg1: */
1494
1495 /* TODO */
1496 }
1497 } else {
1498 error_flag = 1;
1499 error_code = 1111; /* TODO: ultrix ENOMEM? */
1500 }
1501 free(charbuf);
1502 break;
1503
1504 case ULTRIX_SYS_fstat:
1505 result_low = useremul_fstat(cpu, &error_code, arg0, arg1);
1506 break;
1507
1508 case ULTRIX_SYS_getpagesize:
1509 debug("[ getpagesize() ]\n");
1510 result_low = 4096;
1511 break;
1512
1513 case ULTRIX_SYS_getdtablesize:
1514 debug("[ getdtablesize() ]\n");
1515 result_low = getdtablesize();
1516 break;
1517
1518 case ULTRIX_SYS_gethostname:
1519 debug("[ gethostname(0x%llx,%lli) ]\n",
1520 (long long)arg0, (long long)arg1);
1521 result_low = 0;
1522 if (arg1 != 0 && arg1 < 500000) {
1523 unsigned char *buf = malloc(arg1);
1524 unsigned int i;
1525
1526 result_low = gethostname((char *)buf, arg1);
1527 for (i = 0; i<arg1 && i < arg1; i++)
1528 cpu->memory_rw(cpu, cpu->mem, arg0 + i,
1529 &buf[i], 1, MEM_WRITE, CACHE_NONE);
1530
1531 free(buf);
1532 } else {
1533 error_flag = 1;
1534 error_code = 5555; /* TODO */ /* ENOMEM */
1535 }
1536 break;
1537
1538 case ULTRIX_SYS_writev:
1539 descr = arg0;
1540 debug("[ writev(%lli,0x%llx,%lli) ]\n",
1541 (long long)arg0, (long long)arg1, (long long)arg2);
1542
1543 if (arg1 != 0) {
1544 unsigned int i, total = 0;
1545
1546 for (i=0; i<arg2; i++) {
1547 uint32_t iov_base, iov_len;
1548 iov_base = load_32bit_word(cpu,
1549 arg1 + 8*i + 0); /* char * */
1550 iov_len = load_32bit_word(cpu,
1551 arg1 + 8*i + 4); /* size_t */
1552
1553 if (iov_len != 0) {
1554 unsigned char *charbuf =
1555 malloc(iov_len);
1556 if (charbuf == NULL) {
1557 fprintf(stderr, "out of memory"
1558 " in useremul__ultrix()\n");
1559 exit(1);
1560 }
1561
1562 /* TODO: address validity check */
1563 cpu->memory_rw(cpu, cpu->mem, (uint64_t)
1564 iov_base, charbuf, iov_len,
1565 MEM_READ, CACHE_DATA);
1566 total += write(descr, charbuf, iov_len);
1567 free(charbuf);
1568 }
1569 }
1570
1571 result_low = total;
1572 }
1573 break;
1574
1575 case ULTRIX_SYS_gethostid:
1576 debug("[ gethostid() ]\n");
1577 /* This is supposed to return a unique 32-bit host id. */
1578 result_low = 0x12345678;
1579 break;
1580
1581 case ULTRIX_SYS_gettimeofday:
1582 debug("[ gettimeofday(0x%llx,0x%llx) ]\n",
1583 (long long)arg0, (long long)arg1);
1584 result_low = gettimeofday(&tv, &tz);
1585 if (result_low) {
1586 error_flag = 1;
1587 error_code = errno;
1588 } else {
1589 if (arg0 != 0) {
1590 /* Store tv.tv_sec and tv.tv_usec
1591 as 'long' (32-bit) values: */
1592 store_32bit_word(cpu, arg0 + 0, tv.tv_sec);
1593 store_32bit_word(cpu, arg0 + 4, tv.tv_usec);
1594 }
1595 if (arg1 != 0) {
1596 /* Store tz.tz_minuteswest and
1597 tz.tz_dsttime as 'long' (32-bit) values: */
1598 store_32bit_word(cpu, arg1 + 0,
1599 tz.tz_minuteswest);
1600 store_32bit_word(cpu, arg1 + 4, tz.tz_dsttime);
1601 }
1602 }
1603 break;
1604
1605 default:
1606 fatal("[ UNIMPLEMENTED ultrix syscall %i ]\n", sysnr);
1607 error_flag = 1;
1608 error_code = 78; /* ENOSYS */
1609 }
1610
1611 /*
1612 * Ultrix/mips return values:
1613 *
1614 * TODO
1615 *
1616 * a3 is 0 if the syscall was ok, otherwise 1.
1617 * v0 (and sometimes v1) contain the result value.
1618 */
1619 cpu->cd.mips.gpr[MIPS_GPR_A3] = error_flag;
1620 if (error_flag)
1621 cpu->cd.mips.gpr[MIPS_GPR_V0] = error_code;
1622 else
1623 cpu->cd.mips.gpr[MIPS_GPR_V0] = result_low;
1624
1625 if (result_high_set)
1626 cpu->cd.mips.gpr[MIPS_GPR_V1] = result_high;
1627
1628 /* TODO */
1629 }
1630
1631
1632 /*
1633 * useremul_name_to_useremul():
1634 *
1635 * Example:
1636 * Input: name = "netbsd/pmax"
1637 * Output: sets *arch = ARCH_MIPS, *machine_name = "NetBSD/pmax",
1638 * and *cpu_name = "R3000".
1639 */
1640 void useremul_name_to_useremul(struct cpu *cpu, char *name, int *arch,
1641 char **machine_name, char **cpu_name)
1642 {
1643 struct syscall_emul *sep;
1644
1645 sep = first_syscall_emul;
1646
1647 while (sep != NULL) {
1648 if (strcasecmp(name, sep->name) == 0) {
1649 if (cpu_family_ptr_by_number(sep->arch) == NULL) {
1650 printf("\nSupport for the CPU family needed"
1651 " for '%s' userland emulation was not"
1652 " enabled at configuration time.\n",
1653 sep->name);
1654 exit(1);
1655 }
1656
1657 if (cpu != NULL)
1658 cpu->useremul_syscall = sep->f;
1659
1660 if (arch != NULL)
1661 *arch = sep->arch;
1662
1663 if (machine_name != NULL) {
1664 *machine_name = strdup(sep->name);
1665 if (*machine_name == NULL) {
1666 printf("out of memory\n");
1667 exit(1);
1668 }
1669 }
1670
1671 if (cpu_name != NULL) {
1672 *cpu_name = strdup(sep->cpu_name);
1673 if (*cpu_name == NULL) {
1674 printf("out of memory\n");
1675 exit(1);
1676 }
1677 }
1678 return;
1679 }
1680
1681 sep = sep->next;
1682 }
1683
1684 fatal("Unknown userland emulation '%s'\n", name);
1685 exit(1);
1686 }
1687
1688
1689 /*
1690 * add_useremul():
1691 *
1692 * For internal use, from useremul_init() only. Adds an emulation mode.
1693 */
1694 static void add_useremul(char *name, int arch, char *cpu_name,
1695 void (*f)(struct cpu *, uint32_t),
1696 void (*setup)(struct cpu *, int, char **))
1697 {
1698 struct syscall_emul *sep;
1699
1700 sep = malloc(sizeof(struct syscall_emul));
1701 if (sep == NULL) {
1702 printf("add_useremul(): out of memory\n");
1703 exit(1);
1704 }
1705 memset(sep, 0, sizeof(sep));
1706
1707 sep->name = name;
1708 sep->arch = arch;
1709 sep->cpu_name = cpu_name;
1710 sep->f = f;
1711 sep->setup = setup;
1712
1713 sep->next = first_syscall_emul;
1714 first_syscall_emul = sep;
1715 }
1716
1717
1718 /*
1719 * useremul_list_emuls():
1720 *
1721 * List all available userland emulation modes. (Actually, only those which
1722 * have CPU support enabled.)
1723 */
1724 void useremul_list_emuls(void)
1725 {
1726 struct syscall_emul *sep;
1727 int iadd = DEBUG_INDENTATION * 2;
1728
1729 sep = first_syscall_emul;
1730
1731 if (sep == NULL)
1732 return;
1733
1734 debug("The following userland-only (syscall) emulation modes are"
1735 " available:\n\n");
1736 debug_indentation(iadd);
1737
1738 while (sep != NULL) {
1739 if (cpu_family_ptr_by_number(sep->arch) != NULL) {
1740 debug("%s (default CPU \"%s\")\n",
1741 sep->name, sep->cpu_name);
1742 }
1743
1744 sep = sep->next;
1745 }
1746
1747 debug_indentation(-iadd);
1748 debug("\n(Most of these modes are bogus.)\n\n");
1749 }
1750
1751
1752 /*
1753 * useremul_init():
1754 *
1755 * This function should be called before any other useremul_*() function
1756 * is used.
1757 */
1758 void useremul_init(void)
1759 {
1760 /* Note: These are in reverse alphabetic order: */
1761
1762 add_useremul("Ultrix", ARCH_MIPS, "R3000",
1763 useremul__ultrix, useremul__ultrix_setup);
1764
1765 add_useremul("NetBSD/sh", ARCH_SH, "SH4",
1766 useremul__netbsd, useremul__netbsd_setup);
1767
1768 add_useremul("NetBSD/powerpc", ARCH_PPC, "PPC750",
1769 useremul__netbsd, useremul__netbsd_setup);
1770
1771 add_useremul("NetBSD/pmax", ARCH_MIPS, "R3000",
1772 useremul__netbsd, useremul__netbsd_setup);
1773
1774 add_useremul("NetBSD/arm", ARCH_ARM, "SA1110",
1775 useremul__netbsd, useremul__netbsd_setup);
1776
1777 add_useremul("NetBSD/amd64", ARCH_X86, "AMD64",
1778 useremul__netbsd, useremul__netbsd_setup);
1779
1780 add_useremul("NetBSD/alpha", ARCH_ALPHA, "Alpha",
1781 useremul__netbsd, useremul__netbsd_setup);
1782
1783 add_useremul("Linux/PPC64", ARCH_PPC, "PPC970",
1784 useremul__linux, useremul__linux_setup);
1785
1786 add_useremul("FreeBSD/Alpha", ARCH_ALPHA, "Alpha",
1787 useremul__freebsd, useremul__freebsd_setup);
1788 }
1789

  ViewVC Help
Powered by ViewVC 1.1.26