/[gxemul]/upstream/0.3.5/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.3.5/src/useremul.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26