diff --git a/CROMU_00016 b/CROMU_00016 new file mode 100755 index 0000000..6e788ab Binary files /dev/null and b/CROMU_00016 differ diff --git a/patches/version.patch b/patches/version.patch new file mode 100644 index 0000000..144e6f9 --- /dev/null +++ b/patches/version.patch @@ -0,0 +1,22885 @@ +diff --git a/home/gkrishna/Shelly/work/qemu-cgc/CGC_README.md b/home/gkrishna/Shelly/work/qemu-cgc/CGC_README.md +new file mode 120000 +index 0000000..42061c0 +--- /dev/null ++++ b/home/gkrishna/Shelly/work/qemu-cgc/CGC_README.md +@@ -0,0 +1 @@ ++README.md +\ No newline at end of file +diff --git a/home/gkrishna/Shelly/work/qemu/Makefile.objs b/home/gkrishna/Shelly/work/qemu-cgc/Makefile.objs +index 28999d3..149ae03 100644 +--- a/home/gkrishna/Shelly/work/qemu/Makefile.objs ++++ b/home/gkrishna/Shelly/work/qemu-cgc/Makefile.objs +@@ -55,7 +55,7 @@ common-obj-y += qjson.o + + common-obj-$(CONFIG_SPICE) += spice-qemu-char.o + +-common-obj-y += audio/ ++#common-obj-y += audio/ + common-obj-y += hw/ + common-obj-y += accel.o + +diff --git a/home/gkrishna/Shelly/work/qemu-cgc/README.md b/home/gkrishna/Shelly/work/qemu-cgc/README.md +new file mode 100644 +index 0000000..a893665 +--- /dev/null ++++ b/home/gkrishna/Shelly/work/qemu-cgc/README.md +@@ -0,0 +1,167 @@ ++ ++ ++Important differences w.r.t. a regular Linux system: ++ ++ - No signal handling. (But note that QEMU itself needs to handle some of them.) ++ ++ - In particular, no `SIGPIPE` (it's probably OK to just ignore it, `write()` knows it can return `EPIPE`). ++ ++ - Syscall auto-restart (`EINTR` should never be returned) ++ ++ - Syscalls return either 0 or a _positive_ error value. ++ ++ - Only `int 0x80` is allowed. ++ ++ - `ADDR_NO_RANDOMIZE` and `STICKY_TIMEOUTS` are set. ++ ++ ++A `cgc_bytes` field exists in `task_struct`, unclear why (seems to equal the number of bytes handled by the last syscall). ++ ++ ++Initial state ++============= ++ ++https://github.com/CyberGrandChallenge/libcgc/blob/master/cgcabi.md ++ ++ ++Initial stack ++------------- ++ ++Pages are auto-allocated, rwx, zeroed. ++Maximum size: 8MB ++ ++ Initial EIP: 0xbaaaaffc ++ 8MB (max) ++ ++ ++Guess result: ++ 0xbaaa b000 INVALID ++ 0xbaaa afff first valid dword ++ . ++ 0xbaaa affc first valid dword ++ ++ | ++ | grows downward, as usual ++ _ ++ 8 MB max ++ ++ 0xb2aab000 last possible valid dword ++ ++ ++ ++Flag page ++--------- ++ ++Flag page retrieval [PoV type 2] for (this) CFE: ++ ++ any 4 contiguous bytes ++ in ++ page [ 0x4347C000 .. 0x4347CFFF ] ++ ++https://github.com/CyberGrandChallenge/cgc-release-documentation/blob/master/walk-throughs/submitting-a-cb.md ++ ++ ++ ++Simple test with the VM's gdb ++----------------------------- ++ ++maps: ++ ++ 08048000-08049000 r-xp 00000000 fe:01 107659 /home/vagrant/passacarte ++ 4347c000-4347d000 r--p 00000000 00:00 0 ++ baa8b000-baaab000 rwxp 00000000 00:00 0 [stack] ++ ++gdb info: ++ ++ Breakpoint 1, 0x080480c0 in _start () ++ (gdb) info r ++ eax 0x0 0 ++ ecx 0x4347c000 1128775680 ++ edx 0x0 0 ++ ebx 0x0 0 ++ esp 0xbaaaaffc 0xbaaaaffc ++ ebp 0x0 0x0 ++ esi 0x0 0 ++ edi 0x0 0 ++ eip 0x80480c0 0x80480c0 <_start> ++ eflags 0x202 [ IF ] ++ cs 0x73 115 ++ ss 0x7b 123 ++ ds 0x7b 123 ++ es 0x7b 123 ++ fs 0x7b 123 ++ gs 0x7b 123 ++ ++ (gdb) info float ++ R7: Empty 0x00000000000000000000 ++ R6: Empty 0x00000000000000000000 ++ R5: Empty 0x00000000000000000000 ++ R4: Empty 0x00000000000000000000 ++ R3: Empty 0x00000000000000000000 ++ R2: Empty 0x00000000000000000000 ++ R1: Empty 0x00000000000000000000 ++ =>R0: Empty 0x00000000000000000000 ++ ++ Status Word: 0x0000 ++ TOP: 0 ++ Control Word: 0x037f IM DM ZM OM UM PM ++ PC: Extended Precision (64-bits) ++ RC: Round to nearest ++ Tag Word: 0xffff ++ Instruction Pointer: 0x00:0x00000000 ++ Operand Pointer: 0x00:0x00000000 ++ Opcode: 0x0000 ++ ++ ++ (gdb) p *((unsigned char*) 0xbaaab000) ++ Cannot access memory at address 0xbaaab000 ++ ++ (gdb) x/x $esp ++ 0xbaaaaffc: 0x00000000 ++ ++ ++BUT: `p *(unsigned char*)0xba2aa000` ++Causes a kernel panic! ++ ++ kernel BUG at mm/memory.c:1838! ++ invalid opcode: 0000 [#2] SMP ++ Modules linked in: fbcon bitblit softcursor font qxl drm_kms_helper ttm drm i2c_core fb fbdev virtio_blk virtio_net virtio_pci virtio_ring virtio ++ CPU: 0 PID: 3193 Comm: gdb Tainted: G D 3.13.11-ckt21+ #3 ++ Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014 ++ task: c743ccb0 ti: c69a0000 task.ti: c69a0000 ++ EIP: 0060:[] EFLAGS: 00010246 CPU: 0 ++ EIP is at __get_user_pages.part.12+0x429/0x430 ++ EAX: 00000040 EBX: 00000016 ECX: c76c4d40 EDX: 00000000 ++ ESI: c7655880 EDI: c6b4ad70 EBP: ba2aa000 ESP: c69a1dbc ++ DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 ++ CR0: 8005003b CR2: 082dc530 CR3: 06806000 CR4: 000007f0 ++ Stack: ++ c64583c0 00000010 c743ccb0 00000000 00000296 cac74000 c6efbc00 cac74034 ++ 00000296 00000000 c64583c0 00000004 ba2aa000 c69a1e74 c10af378 00000001 ++ 00000016 c69a1e24 c69a1e20 00000000 c1097071 c64583c0 c6b4ad70 00000016 ++ Call Trace: ++ [] ? __access_remote_vm+0xb8/0x160 ++ [] ? get_page_from_freelist+0x431/0x540 ++ [] ? access_process_vm+0x29/0x50 ++ [] ? ptrace_request+0x49f/0x6d0 ++ [] ? __do_fault+0x419/0x5d0 ++ [] ? handle_mm_fault+0x11d/0xa10 ++ [] ? arch_ptrace+0x320/0x4b0 ++ [] ? __do_page_fault+0x163/0x460 ++ [] ? __do_page_fault+0x236/0x460 ++ [] ? task_rq_lock+0x3a/0x70 ++ [] ? wait_task_inactive+0x72/0xe0 ++ [] ? SyS_ptrace+0x20b/0x580 ++ [] ? default_syscall+0x12/0x12 ++ Code: e0 05 03 05 e4 c2 54 c1 89 c2 e9 58 ff ff ff 89 d0 89 54 24 20 e8 08 b7 fe ff 8b 54 24 20 84 c0 0f 85 8a fd ff ff e9 52 ff ff ff <0f> 0b 90 8d 74 26 00 55 57 56 53 83 ec 04 8b 74 24 1c 8b 5c 24 ++ EIP: [] __get_user_pages.part.12+0x429/0x430 SS:ESP 0068:c69a1dbc ++ ++ ++ ++configure ++========= ++ ++Use either `./cgc_configure_debug` or `./cgc_configure_opt` ++ ++(Note that `--disable-werror` should not be necessary, but you may not want to waste time on that.) ++ +diff --git a/home/gkrishna/Shelly/work/qemu-cgc/README.qemu b/home/gkrishna/Shelly/work/qemu-cgc/README.qemu +new file mode 100644 +index 0000000..c7c990d +--- /dev/null ++++ b/home/gkrishna/Shelly/work/qemu-cgc/README.qemu +@@ -0,0 +1,3 @@ ++Read the documentation in qemu-doc.html or on http://wiki.qemu-project.org ++ ++- QEMU team +diff --git a/home/gkrishna/Shelly/work/qemu-cgc/cgc_configure_afl_debug b/home/gkrishna/Shelly/work/qemu-cgc/cgc_configure_afl_debug +new file mode 100755 +index 0000000..64d9d8b +--- /dev/null ++++ b/home/gkrishna/Shelly/work/qemu-cgc/cgc_configure_afl_debug +@@ -0,0 +1,5 @@ ++#!/bin/bash ++ ++./configure \ ++ --disable-tools --disable-netmap --disable-spice --disable-curl --disable-virtfs --disable-qom-cast-debug --disable-vde --disable-libnfs --disable-libiscsi --disable-curses --disable-fdt --disable-rbd --disable-opengl --disable-lzo --disable-usb-redir --disable-xfsctl --disable-snappy --disable-bzip2 --disable-guest-agent --disable-glusterfs --disable-vte --disable-vhdx --disable-libssh2 --disable-quorum --disable-tpm --disable-smartcard-nss --disable-libusb --disable-vhost-scsi --disable-vhost-net --disable-docs --disable-zlib-test --disable-bluez --disable-brlapi --disable-kvm \ ++ --disable-system --enable-linux-user --enable-guest-base --disable-gtk --disable-sdl --disable-vnc --target-list=i386-linux-user --enable-debug --disable-werror --extra-cflags='-DAFL -g3 -ggdb -gdwarf-4' --python=`which python2` +diff --git a/home/gkrishna/Shelly/work/qemu-cgc/cgc_configure_afl_opt b/home/gkrishna/Shelly/work/qemu-cgc/cgc_configure_afl_opt +new file mode 100755 +index 0000000..7f36c30 +--- /dev/null ++++ b/home/gkrishna/Shelly/work/qemu-cgc/cgc_configure_afl_opt +@@ -0,0 +1,7 @@ ++#!/bin/sh ++ ++# Like what AFL does, but without -Werror ++ ++CFLAGS="-O3" ./configure \ ++ --disable-tools --disable-netmap --disable-spice --disable-curl --disable-virtfs --disable-qom-cast-debug --disable-vde --disable-libnfs --disable-libiscsi --disable-curses --disable-fdt --disable-rbd --disable-opengl --disable-lzo --disable-usb-redir --disable-xfsctl --disable-snappy --disable-bzip2 --disable-guest-agent --disable-glusterfs --disable-vte --disable-vhdx --disable-libssh2 --disable-quorum --disable-tpm --disable-smartcard-nss --disable-libusb --disable-vhost-scsi --disable-vhost-net --disable-docs --disable-zlib-test --disable-bluez --disable-brlapi --disable-kvm \ ++ --disable-system --enable-linux-user --enable-guest-base --disable-gtk --disable-sdl --disable-vnc --target-list=i386-linux-user --disable-werror --extra-cflags='-DAFL' --python=`which python2` +diff --git a/home/gkrishna/Shelly/work/qemu-cgc/cgc_configure_debug b/home/gkrishna/Shelly/work/qemu-cgc/cgc_configure_debug +new file mode 100755 +index 0000000..f9e912a +--- /dev/null ++++ b/home/gkrishna/Shelly/work/qemu-cgc/cgc_configure_debug +@@ -0,0 +1,5 @@ ++#!/bin/bash ++ ++./configure \ ++ --disable-tools --disable-netmap --disable-spice --disable-curl --disable-virtfs --disable-qom-cast-debug --disable-vde --disable-libnfs --disable-libiscsi --disable-curses --disable-fdt --disable-rbd --disable-opengl --disable-lzo --disable-usb-redir --disable-xfsctl --disable-snappy --disable-bzip2 --disable-guest-agent --disable-glusterfs --disable-vte --disable-vhdx --disable-libssh2 --disable-quorum --disable-tpm --disable-smartcard-nss --disable-libusb --disable-vhost-scsi --disable-vhost-net --disable-docs --disable-zlib-test --disable-bluez --disable-brlapi --disable-kvm \ ++ --disable-system --enable-linux-user --enable-guest-base --disable-gtk --disable-sdl --disable-vnc --target-list=i386-linux-user --enable-debug --disable-werror --extra-cflags='-DDEBUG_MMAP -DDEBUG_STACK -DDEBUG_SIGNAL -g3 -ggdb -gdwarf-4' --python=`which python2` +diff --git a/home/gkrishna/Shelly/work/qemu-cgc/cgc_configure_nxtracer_debug b/home/gkrishna/Shelly/work/qemu-cgc/cgc_configure_nxtracer_debug +new file mode 100755 +index 0000000..81dcb51 +--- /dev/null ++++ b/home/gkrishna/Shelly/work/qemu-cgc/cgc_configure_nxtracer_debug +@@ -0,0 +1,5 @@ ++#!/bin/bash ++ ++./configure \ ++ --disable-tools --disable-netmap --disable-spice --disable-curl --disable-virtfs --disable-qom-cast-debug --disable-vde --disable-libnfs --disable-libiscsi --disable-curses --disable-fdt --disable-rbd --disable-opengl --disable-lzo --disable-usb-redir --disable-xfsctl --disable-snappy --disable-bzip2 --disable-guest-agent --disable-glusterfs --disable-vte --disable-vhdx --disable-libssh2 --disable-quorum --disable-tpm --disable-smartcard-nss --disable-libusb --disable-vhost-scsi --disable-vhost-net --disable-docs --disable-zlib-test --disable-bluez --disable-brlapi --disable-kvm \ ++ --disable-system --enable-linux-user --enable-guest-base --disable-gtk --disable-sdl --disable-vnc --target-list=i386-linux-user --enable-debug --disable-werror --extra-cflags='-DENFORCE_NX -DTRACER -g3 -ggdb -gdwarf-4' --python=`which python2` +diff --git a/home/gkrishna/Shelly/work/qemu-cgc/cgc_configure_nxtracer_opt b/home/gkrishna/Shelly/work/qemu-cgc/cgc_configure_nxtracer_opt +new file mode 100755 +index 0000000..cdac4a7 +--- /dev/null ++++ b/home/gkrishna/Shelly/work/qemu-cgc/cgc_configure_nxtracer_opt +@@ -0,0 +1,7 @@ ++#!/bin/sh ++ ++# Like what AFL does, but without -Werror ++ ++CFLAGS="-O3" ./configure \ ++ --disable-tools --disable-netmap --disable-spice --disable-curl --disable-virtfs --disable-qom-cast-debug --disable-vde --disable-libnfs --disable-libiscsi --disable-curses --disable-fdt --disable-rbd --disable-opengl --disable-lzo --disable-usb-redir --disable-xfsctl --disable-snappy --disable-bzip2 --disable-guest-agent --disable-glusterfs --disable-vte --disable-vhdx --disable-libssh2 --disable-quorum --disable-tpm --disable-smartcard-nss --disable-libusb --disable-vhost-scsi --disable-vhost-net --disable-docs --disable-zlib-test --disable-bluez --disable-brlapi --disable-kvm \ ++ --disable-system --enable-linux-user --enable-guest-base --disable-gtk --disable-sdl --disable-vnc --target-list=i386-linux-user --disable-werror --extra-cflags='-DENFORCE_NX -DTRACER' --python=`which python2` +diff --git a/home/gkrishna/Shelly/work/qemu-cgc/cgc_configure_opt b/home/gkrishna/Shelly/work/qemu-cgc/cgc_configure_opt +new file mode 100755 +index 0000000..7abcc79 +--- /dev/null ++++ b/home/gkrishna/Shelly/work/qemu-cgc/cgc_configure_opt +@@ -0,0 +1,7 @@ ++#!/bin/sh ++ ++# Like what AFL does, but without -Werror ++ ++CFLAGS="-O3" ./configure \ ++ --disable-tools --disable-netmap --disable-spice --disable-curl --disable-virtfs --disable-qom-cast-debug --disable-vde --disable-libnfs --disable-libiscsi --disable-curses --disable-fdt --disable-rbd --disable-opengl --disable-lzo --disable-usb-redir --disable-xfsctl --disable-snappy --disable-bzip2 --disable-guest-agent --disable-glusterfs --disable-vte --disable-vhdx --disable-libssh2 --disable-quorum --disable-tpm --disable-smartcard-nss --disable-libusb --disable-vhost-scsi --disable-vhost-net --disable-docs --disable-zlib-test --disable-bluez --disable-brlapi --disable-kvm \ ++ --disable-system --enable-linux-user --enable-guest-base --disable-gtk --disable-sdl --disable-vnc --target-list=i386-linux-user --disable-werror --python=`which python2` +diff --git a/home/gkrishna/Shelly/work/qemu-cgc/cgc_configure_tracer_debug b/home/gkrishna/Shelly/work/qemu-cgc/cgc_configure_tracer_debug +new file mode 100755 +index 0000000..c1e8b2f +--- /dev/null ++++ b/home/gkrishna/Shelly/work/qemu-cgc/cgc_configure_tracer_debug +@@ -0,0 +1,5 @@ ++#!/bin/bash ++ ++./configure \ ++ --disable-tools --disable-netmap --disable-spice --disable-curl --disable-virtfs --disable-qom-cast-debug --disable-vde --disable-libnfs --disable-libiscsi --disable-curses --disable-fdt --disable-rbd --disable-opengl --disable-lzo --disable-usb-redir --disable-xfsctl --disable-snappy --disable-bzip2 --disable-guest-agent --disable-glusterfs --disable-vte --disable-vhdx --disable-libssh2 --disable-quorum --disable-tpm --disable-smartcard-nss --disable-libusb --disable-vhost-scsi --disable-vhost-net --disable-docs --disable-zlib-test --disable-bluez --disable-brlapi --disable-kvm \ ++ --disable-system --enable-linux-user --enable-guest-base --disable-gtk --disable-sdl --disable-vnc --target-list=i386-linux-user --enable-debug --disable-werror --extra-cflags='-DTRACER -g3 -ggdb -gdwarf-4' --python=`which python2` +diff --git a/home/gkrishna/Shelly/work/qemu-cgc/cgc_configure_tracer_opt b/home/gkrishna/Shelly/work/qemu-cgc/cgc_configure_tracer_opt +new file mode 100755 +index 0000000..951ff70 +--- /dev/null ++++ b/home/gkrishna/Shelly/work/qemu-cgc/cgc_configure_tracer_opt +@@ -0,0 +1,7 @@ ++#!/bin/sh ++ ++# Like what AFL does, but without -Werror ++ ++CFLAGS="-O3" ./configure \ ++ --disable-tools --disable-netmap --disable-spice --disable-curl --disable-virtfs --disable-qom-cast-debug --disable-vde --disable-libnfs --disable-libiscsi --disable-curses --disable-fdt --disable-rbd --disable-opengl --disable-lzo --disable-usb-redir --disable-xfsctl --disable-snappy --disable-bzip2 --disable-guest-agent --disable-glusterfs --disable-vte --disable-vhdx --disable-libssh2 --disable-quorum --disable-tpm --disable-smartcard-nss --disable-libusb --disable-vhost-scsi --disable-vhost-net --disable-docs --disable-zlib-test --disable-bluez --disable-brlapi --disable-kvm \ ++ --disable-system --enable-linux-user --enable-guest-base --disable-gtk --disable-sdl --disable-vnc --target-list=i386-linux-user --disable-werror --extra-cflags='-DTRACER' --python=`which python2` +diff --git a/home/gkrishna/Shelly/work/qemu/configure b/home/gkrishna/Shelly/work/qemu-cgc/configure +index 6969f6f..01eb454 100755 +--- a/home/gkrishna/Shelly/work/qemu/configure ++++ b/home/gkrishna/Shelly/work/qemu-cgc/configure +@@ -5451,14 +5451,13 @@ if test "$numa" = "yes"; then + fi + + # build tree in object directory in case the source is not in the current directory +-DIRS="tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos tests/qapi-schema tests/tcg/xtensa tests/qemu-iotests" ++DIRS="tests tests/tcg tests/libqos tests/qapi-schema tests/qemu-iotests" + DIRS="$DIRS fsdev" + DIRS="$DIRS pc-bios/optionrom pc-bios/spapr-rtas pc-bios/s390-ccw" + DIRS="$DIRS roms/seabios roms/vgabios" + DIRS="$DIRS qapi-generated" + FILES="Makefile tests/tcg/Makefile qdict-test-data.txt" +-FILES="$FILES tests/tcg/cris/Makefile tests/tcg/cris/.gdbinit" +-FILES="$FILES tests/tcg/lm32/Makefile tests/tcg/xtensa/Makefile po/Makefile" ++FILES="$FILES po/Makefile" + FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps" + FILES="$FILES pc-bios/spapr-rtas/Makefile" + FILES="$FILES pc-bios/s390-ccw/Makefile" +diff --git a/home/gkrishna/Shelly/work/qemu/cpu-exec.c b/home/gkrishna/Shelly/work/qemu-cgc/cpu-exec.c +index 2ffeb6e..b5c2d6c 100644 +--- a/home/gkrishna/Shelly/work/qemu/cpu-exec.c ++++ b/home/gkrishna/Shelly/work/qemu-cgc/cpu-exec.c +@@ -28,6 +28,10 @@ + #include "exec/memory-internal.h" + #include "qemu/rcu.h" + ++#ifdef AFL ++#include "../patches/afl-qemu-cpu-inl.h" ++#endif ++ + /* -icount align implementation. */ + + typedef struct SyncClocks { +@@ -297,6 +301,9 @@ static TranslationBlock *tb_find_slow(CPUArchState *env, + not_found: + /* if no translated code available, then translate it now */ + tb = tb_gen_code(cpu, pc, cs_base, flags, 0); ++#ifdef AFL ++ AFL_QEMU_CPU_SNIPPET1; ++#endif + + found: + /* Move the last found TB to the head of the list */ +@@ -492,10 +499,19 @@ int cpu_exec(CPUArchState *env) + next_tb = 0; + tcg_ctx.tb_ctx.tb_invalidated_flag = 0; + } ++#ifdef AFL ++ /* remove the forkserver stuff from AFL_QEMU_CPU_SNIPPET2 ++ * it's been moved to do_receive */ ++ do { ++ afl_maybe_log(tb->pc); ++ } while(0); ++#endif + if (qemu_loglevel_mask(CPU_LOG_EXEC)) { + qemu_log("Trace %p [" TARGET_FMT_lx "] %s\n", + tb->tc_ptr, tb->pc, lookup_symbol(tb->pc)); + } ++#ifndef TRACER ++ /* tracer needs to see every basic block transition */ + /* see if we can patch the calling TB. When the TB + spans two pages, we cannot safely do a direct + jump. */ +@@ -503,6 +519,7 @@ int cpu_exec(CPUArchState *env) + tb_add_jump((TranslationBlock *)(next_tb & ~TB_EXIT_MASK), + next_tb & TB_EXIT_MASK, tb); + } ++#endif + have_tb_lock = false; + spin_unlock(&tcg_ctx.tb_ctx.tb_lock); + +diff --git a/home/gkrishna/Shelly/work/qemu/fpu/softfloat.c b/home/gkrishna/Shelly/work/qemu-cgc/fpu/softfloat.c +index f1170fe..d039bda 100644 +--- a/home/gkrishna/Shelly/work/qemu/fpu/softfloat.c ++++ b/home/gkrishna/Shelly/work/qemu-cgc/fpu/softfloat.c +@@ -5569,8 +5569,12 @@ floatx80 floatx80_sqrt(floatx80 a, float_status *status) + z.high = floatx80_default_nan_high; + return z; + } ++ if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 ); ++ while (aExp != 0 && (aSig0 & 0x8000000000000000) == 0) { ++ aExp--; ++ aSig0 <<= 1; ++ } + if ( aExp == 0 ) { +- if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 ); + normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); + } + zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFF; +diff --git a/home/gkrishna/Shelly/work/qemu/hw/Makefile.objs b/home/gkrishna/Shelly/work/qemu-cgc/hw/Makefile.objs +index 73afa41..1ce710f 100644 +--- a/home/gkrishna/Shelly/work/qemu/hw/Makefile.objs ++++ b/home/gkrishna/Shelly/work/qemu-cgc/hw/Makefile.objs +@@ -1,36 +1,3 @@ +-devices-dirs-$(call land, $(CONFIG_VIRTIO),$(call land,$(CONFIG_VIRTFS),$(CONFIG_PCI))) += 9pfs/ +-devices-dirs-$(CONFIG_ACPI) += acpi/ +-devices-dirs-$(CONFIG_SOFTMMU) += audio/ +-devices-dirs-$(CONFIG_SOFTMMU) += block/ +-devices-dirs-$(CONFIG_SOFTMMU) += bt/ +-devices-dirs-$(CONFIG_SOFTMMU) += char/ +-devices-dirs-$(CONFIG_SOFTMMU) += cpu/ +-devices-dirs-$(CONFIG_SOFTMMU) += display/ +-devices-dirs-$(CONFIG_SOFTMMU) += dma/ +-devices-dirs-$(CONFIG_SOFTMMU) += gpio/ +-devices-dirs-$(CONFIG_SOFTMMU) += i2c/ +-devices-dirs-$(CONFIG_SOFTMMU) += ide/ +-devices-dirs-$(CONFIG_SOFTMMU) += input/ +-devices-dirs-$(CONFIG_SOFTMMU) += intc/ +-devices-dirs-$(CONFIG_IPACK) += ipack/ +-devices-dirs-$(CONFIG_SOFTMMU) += isa/ +-devices-dirs-$(CONFIG_SOFTMMU) += misc/ +-devices-dirs-$(CONFIG_SOFTMMU) += net/ +-devices-dirs-$(CONFIG_SOFTMMU) += nvram/ +-devices-dirs-$(CONFIG_SOFTMMU) += pci/ +-devices-dirs-$(CONFIG_PCI) += pci-bridge/ pci-host/ +-devices-dirs-$(CONFIG_SOFTMMU) += pcmcia/ +-devices-dirs-$(CONFIG_SOFTMMU) += scsi/ +-devices-dirs-$(CONFIG_SOFTMMU) += sd/ +-devices-dirs-$(CONFIG_SOFTMMU) += ssi/ +-devices-dirs-$(CONFIG_SOFTMMU) += timer/ +-devices-dirs-$(CONFIG_TPM) += tpm/ +-devices-dirs-$(CONFIG_SOFTMMU) += usb/ +-devices-dirs-$(CONFIG_SOFTMMU) += vfio/ +-devices-dirs-$(CONFIG_VIRTIO) += virtio/ +-devices-dirs-$(CONFIG_SOFTMMU) += watchdog/ +-devices-dirs-$(CONFIG_SOFTMMU) += xen/ +-devices-dirs-$(CONFIG_MEM_HOTPLUG) += mem/ + devices-dirs-y += core/ + common-obj-y += $(devices-dirs-y) + obj-y += $(devices-dirs-y) +diff --git a/home/gkrishna/Shelly/work/qemu/include/elf.h b/home/gkrishna/Shelly/work/qemu-cgc/include/elf.h +index 3e75f05..f067896 100644 +--- a/home/gkrishna/Shelly/work/qemu/include/elf.h ++++ b/home/gkrishna/Shelly/work/qemu-cgc/include/elf.h +@@ -1435,6 +1435,12 @@ typedef struct elf64_shdr { + #define ELFMAG "\177ELF" + #define SELFMAG 4 + ++#define CGCMAG0 0x7f /* EI_MAG */ ++#define CGCMAG1 'C' ++#define CGCMAG2 'G' ++#define CGCMAG3 'C' ++#define CGCMAG "\177CGC" ++ + #define ELFCLASSNONE 0 /* EI_CLASS */ + #define ELFCLASS32 1 + #define ELFCLASS64 2 +diff --git a/home/gkrishna/Shelly/work/qemu/include/exec/cpu-all.h b/home/gkrishna/Shelly/work/qemu-cgc/include/exec/cpu-all.h +index ac06c67..6f7dcba 100644 +--- a/home/gkrishna/Shelly/work/qemu/include/exec/cpu-all.h ++++ b/home/gkrishna/Shelly/work/qemu-cgc/include/exec/cpu-all.h +@@ -157,7 +157,7 @@ static inline void tswap64s(uint64_t *s) + #if defined(CONFIG_USE_GUEST_BASE) + extern unsigned long guest_base; + extern int have_guest_base; +-extern unsigned long reserved_va; ++static const unsigned long reserved_va = 0xf7000000; //extern unsigned long reserved_va; + #define GUEST_BASE guest_base + #define RESERVED_VA reserved_va + #else +@@ -175,12 +175,16 @@ extern unsigned long reserved_va; + #define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1) + #define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK) + +-/* ??? These should be the larger of uintptr_t and target_ulong. */ +-extern uintptr_t qemu_real_host_page_size; +-extern uintptr_t qemu_host_page_size; +-extern uintptr_t qemu_host_page_mask; +- +-#define HOST_PAGE_ALIGN(addr) (((addr) + qemu_host_page_size - 1) & qemu_host_page_mask) ++#if defined(__i386__) || defined(__amd64__) ++// CHANGED: attempt at speeding up memory access for CGC ++static const uintptr_t qemu_real_host_page_size = 4096; ++static const uintptr_t qemu_host_page_size = 4096; ++static const uintptr_t qemu_host_page_mask = ~(((uintptr_t) 4096) - 1); ++#else ++# error Made page size constant for CGC, compile me on x86/x64! ++#endif ++#define HOST_PAGE_ALIGN(addr) (((addr) + ((uintptr_t) 4096) - 1) & ~(((uintptr_t) 4096) - 1)) ++//#define HOST_PAGE_ALIGN(addr) (((addr) + qemu_host_page_size - 1) & qemu_host_page_mask) + + /* same as PROT_xxx */ + #define PAGE_READ 0x0001 +@@ -206,6 +210,7 @@ int walk_memory_regions(void *, walk_memory_regions_fn); + int page_get_flags(target_ulong address); + void page_set_flags(target_ulong start, target_ulong end, int flags); + int page_check_range(target_ulong start, target_ulong len, int flags); ++target_long valid_len(target_ulong start, target_ulong len, int flags); + #endif + + CPUArchState *cpu_copy(CPUArchState *env); +diff --git a/home/gkrishna/Shelly/work/qemu/include/qemu/log.h b/home/gkrishna/Shelly/work/qemu-cgc/include/qemu/log.h +index 195f665..04450c6 100644 +--- a/home/gkrishna/Shelly/work/qemu/include/qemu/log.h ++++ b/home/gkrishna/Shelly/work/qemu-cgc/include/qemu/log.h +@@ -41,6 +41,8 @@ static inline bool qemu_log_enabled(void) + #define LOG_UNIMP (1 << 10) + #define LOG_GUEST_ERROR (1 << 11) + #define CPU_LOG_MMU (1 << 12) ++#define LOG_CIRCULAR_BUFFER (1 << 13) ++ + + /* Returns true if a bit is set in the current loglevel mask + */ +diff --git a/home/gkrishna/Shelly/work/qemu/linux-user/Makefile.objs b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/Makefile.objs +index fd50217..e935372 100644 +--- a/home/gkrishna/Shelly/work/qemu/linux-user/Makefile.objs ++++ b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/Makefile.objs +@@ -1,7 +1,2 @@ + obj-y = main.o syscall.o strace.o mmap.o signal.o \ +- elfload.o linuxload.o uaccess.o uname.o +- +-obj-$(TARGET_HAS_BFLT) += flatload.o +-obj-$(TARGET_I386) += vm86.o +-obj-$(TARGET_ARM) += arm/nwfpe/ +-obj-$(TARGET_M68K) += m68k-sim.o ++ elfload.o linuxload.o uaccess.o +diff --git a/home/gkrishna/Shelly/work/qemu/linux-user/elfload.c b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/elfload.c +index 399c021..a8bc667 100644 +--- a/home/gkrishna/Shelly/work/qemu/linux-user/elfload.c ++++ b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/elfload.c +@@ -16,85 +16,21 @@ + #include "qemu.h" + #include "disas/disas.h" + +-#ifdef _ARCH_PPC64 +-#undef ARCH_DLINFO +-#undef ELF_PLATFORM +-#undef ELF_HWCAP +-#undef ELF_HWCAP2 +-#undef ELF_CLASS +-#undef ELF_DATA +-#undef ELF_ARCH ++#ifndef TARGET_I386 ++#error CGC is i386 only! + #endif + +-#define ELF_OSABI ELFOSABI_SYSV +- +-/* from personality.h */ +- +-/* +- * Flags for bug emulation. +- * +- * These occupy the top three bytes. +- */ +-enum { +- ADDR_NO_RANDOMIZE = 0x0040000, /* disable randomization of VA space */ +- FDPIC_FUNCPTRS = 0x0080000, /* userspace function ptrs point to +- descriptors (signal handling) */ +- MMAP_PAGE_ZERO = 0x0100000, +- ADDR_COMPAT_LAYOUT = 0x0200000, +- READ_IMPLIES_EXEC = 0x0400000, +- ADDR_LIMIT_32BIT = 0x0800000, +- SHORT_INODE = 0x1000000, +- WHOLE_SECONDS = 0x2000000, +- STICKY_TIMEOUTS = 0x4000000, +- ADDR_LIMIT_3GB = 0x8000000, +-}; + +-/* +- * Personality types. +- * +- * These go in the low byte. Avoid using the top bit, it will +- * conflict with error returns. +- */ +-enum { +- PER_LINUX = 0x0000, +- PER_LINUX_32BIT = 0x0000 | ADDR_LIMIT_32BIT, +- PER_LINUX_FDPIC = 0x0000 | FDPIC_FUNCPTRS, +- PER_SVR4 = 0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO, +- PER_SVR3 = 0x0002 | STICKY_TIMEOUTS | SHORT_INODE, +- PER_SCOSVR3 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS | SHORT_INODE, +- PER_OSR5 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS, +- PER_WYSEV386 = 0x0004 | STICKY_TIMEOUTS | SHORT_INODE, +- PER_ISCR4 = 0x0005 | STICKY_TIMEOUTS, +- PER_BSD = 0x0006, +- PER_SUNOS = 0x0006 | STICKY_TIMEOUTS, +- PER_XENIX = 0x0007 | STICKY_TIMEOUTS | SHORT_INODE, +- PER_LINUX32 = 0x0008, +- PER_LINUX32_3GB = 0x0008 | ADDR_LIMIT_3GB, +- PER_IRIX32 = 0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */ +- PER_IRIXN32 = 0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */ +- PER_IRIX64 = 0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */ +- PER_RISCOS = 0x000c, +- PER_SOLARIS = 0x000d | STICKY_TIMEOUTS, +- PER_UW7 = 0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO, +- PER_OSF4 = 0x000f, /* OSF/1 v4 */ +- PER_HPUX = 0x0010, +- PER_MASK = 0x00ff, +-}; ++#ifdef _ARCH_PPC64 ++#error removed ++#endif + +-/* +- * Return the base personality without flags. +- */ +-#define personality(pers) (pers & PER_MASK) ++#define ELF_OSABI ELFOSABI_SYSV + +-/* this flag is uneffective under linux too, should be deleted */ +-#ifndef MAP_DENYWRITE +-#define MAP_DENYWRITE 0 ++#ifdef AFL ++extern abi_ulong afl_entry_point, afl_start_code, afl_end_code; + #endif + +-/* should probably go in elf.h */ +-#ifndef ELIBBAD +-#define ELIBBAD 80 +-#endif + + #ifdef TARGET_WORDS_BIGENDIAN + #define ELF_DATA ELFDATA2MSB +@@ -103,8 +39,7 @@ enum { + #endif + + #ifdef TARGET_ABI_MIPSN32 +-typedef abi_ullong target_elf_greg_t; +-#define tswapreg(ptr) tswap64(ptr) ++#error removed + #else + typedef abi_ulong target_elf_greg_t; + #define tswapreg(ptr) tswapal(ptr) +@@ -119,87 +54,11 @@ typedef abi_uint target_gid_t; + #endif + typedef abi_int target_pid_t; + +-#ifdef TARGET_I386 +- +-#define ELF_PLATFORM get_elf_platform() +- +-static const char *get_elf_platform(void) +-{ +- static char elf_platform[] = "i386"; +- int family = object_property_get_int(OBJECT(thread_cpu), "family", NULL); +- if (family > 6) +- family = 6; +- if (family >= 3) +- elf_platform[1] = '0' + family; +- return elf_platform; +-} +- +-#define ELF_HWCAP get_elf_hwcap() +- +-static uint32_t get_elf_hwcap(void) +-{ +- X86CPU *cpu = X86_CPU(thread_cpu); +- +- return cpu->env.features[FEAT_1_EDX]; +-} +- +-#ifdef TARGET_X86_64 +-#define ELF_START_MMAP 0x2aaaaab000ULL +-#define elf_check_arch(x) ( ((x) == ELF_ARCH) ) +- +-#define ELF_CLASS ELFCLASS64 +-#define ELF_ARCH EM_X86_64 +- +-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) +-{ +- regs->rax = 0; +- regs->rsp = infop->start_stack; +- regs->rip = infop->entry; +-} +- +-#define ELF_NREG 27 +-typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; +- +-/* +- * Note that ELF_NREG should be 29 as there should be place for +- * TRAPNO and ERR "registers" as well but linux doesn't dump +- * those. +- * +- * See linux kernel: arch/x86/include/asm/elf.h +- */ +-static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *env) +-{ +- (*regs)[0] = env->regs[15]; +- (*regs)[1] = env->regs[14]; +- (*regs)[2] = env->regs[13]; +- (*regs)[3] = env->regs[12]; +- (*regs)[4] = env->regs[R_EBP]; +- (*regs)[5] = env->regs[R_EBX]; +- (*regs)[6] = env->regs[11]; +- (*regs)[7] = env->regs[10]; +- (*regs)[8] = env->regs[9]; +- (*regs)[9] = env->regs[8]; +- (*regs)[10] = env->regs[R_EAX]; +- (*regs)[11] = env->regs[R_ECX]; +- (*regs)[12] = env->regs[R_EDX]; +- (*regs)[13] = env->regs[R_ESI]; +- (*regs)[14] = env->regs[R_EDI]; +- (*regs)[15] = env->regs[R_EAX]; /* XXX */ +- (*regs)[16] = env->eip; +- (*regs)[17] = env->segs[R_CS].selector & 0xffff; +- (*regs)[18] = env->eflags; +- (*regs)[19] = env->regs[R_ESP]; +- (*regs)[20] = env->segs[R_SS].selector & 0xffff; +- (*regs)[21] = env->segs[R_FS].selector & 0xffff; +- (*regs)[22] = env->segs[R_GS].selector & 0xffff; +- (*regs)[23] = env->segs[R_DS].selector & 0xffff; +- (*regs)[24] = env->segs[R_ES].selector & 0xffff; +- (*regs)[25] = env->segs[R_FS].selector & 0xffff; +- (*regs)[26] = env->segs[R_GS].selector & 0xffff; +-} +- +-#else ++unsigned long cgc_stack_top; ++unsigned long max_stack_top; + ++/* Note: the actual start_mmap is reset in main.c to reserved_va (first), and ++ * to the value copied from the VM later. This is quite weird, but should work. */ + #define ELF_START_MMAP 0x80000000 + + /* +@@ -227,6 +86,20 @@ static inline void init_thread(struct target_pt_regs *regs, + + A value of 0 tells we have no such handler. */ + regs->edx = 0; ++ ++ /* initialize %ecx to the value of the address of the CGC magic ++ page */ ++ regs->ecx = CGC_MAGIC_PAGE_ADDR; ++ ++ regs->eax = regs->ebx = regs->edi = regs->esi = regs->ebp = 0; ++ ++ if (regs->esp != CGC_INITIAL_SP) { ++ fprintf(stderr, "OUR QEMU/CGC ERROR: init_thread's ESP != DARPA's mandated one (0x%08x != 0x%08x)\n", (unsigned) regs->esp, CGC_INITIAL_SP); ++ exit(-90); ++ } ++ ++ /* CGC TODO: check/set eflags, floating point, XMM [J] */ ++ /* Note: segments are initialized once and for all in main.c (incl. GDT/IDT/...) */ + } + + #define ELF_NREG 17 +@@ -259,943 +132,11 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *en + (*regs)[15] = env->regs[R_ESP]; + (*regs)[16] = env->segs[R_SS].selector & 0xffff; + } +-#endif +- +-#define USE_ELF_CORE_DUMP +-#define ELF_EXEC_PAGESIZE 4096 +- +-#endif +- +-#ifdef TARGET_ARM +- +-#ifndef TARGET_AARCH64 +-/* 32 bit ARM definitions */ +- +-#define ELF_START_MMAP 0x80000000 +- +-#define elf_check_arch(x) ((x) == ELF_MACHINE) +- +-#define ELF_ARCH ELF_MACHINE +-#define ELF_CLASS ELFCLASS32 +- +-static inline void init_thread(struct target_pt_regs *regs, +- struct image_info *infop) +-{ +- abi_long stack = infop->start_stack; +- memset(regs, 0, sizeof(*regs)); +- +- regs->ARM_cpsr = 0x10; +- if (infop->entry & 1) +- regs->ARM_cpsr |= CPSR_T; +- regs->ARM_pc = infop->entry & 0xfffffffe; +- regs->ARM_sp = infop->start_stack; +- /* FIXME - what to for failure of get_user()? */ +- get_user_ual(regs->ARM_r2, stack + 8); /* envp */ +- get_user_ual(regs->ARM_r1, stack + 4); /* envp */ +- /* XXX: it seems that r0 is zeroed after ! */ +- regs->ARM_r0 = 0; +- /* For uClinux PIC binaries. */ +- /* XXX: Linux does this only on ARM with no MMU (do we care ?) */ +- regs->ARM_r10 = infop->start_data; +-} +- +-#define ELF_NREG 18 +-typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; +- +-static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUARMState *env) +-{ +- (*regs)[0] = tswapreg(env->regs[0]); +- (*regs)[1] = tswapreg(env->regs[1]); +- (*regs)[2] = tswapreg(env->regs[2]); +- (*regs)[3] = tswapreg(env->regs[3]); +- (*regs)[4] = tswapreg(env->regs[4]); +- (*regs)[5] = tswapreg(env->regs[5]); +- (*regs)[6] = tswapreg(env->regs[6]); +- (*regs)[7] = tswapreg(env->regs[7]); +- (*regs)[8] = tswapreg(env->regs[8]); +- (*regs)[9] = tswapreg(env->regs[9]); +- (*regs)[10] = tswapreg(env->regs[10]); +- (*regs)[11] = tswapreg(env->regs[11]); +- (*regs)[12] = tswapreg(env->regs[12]); +- (*regs)[13] = tswapreg(env->regs[13]); +- (*regs)[14] = tswapreg(env->regs[14]); +- (*regs)[15] = tswapreg(env->regs[15]); +- +- (*regs)[16] = tswapreg(cpsr_read((CPUARMState *)env)); +- (*regs)[17] = tswapreg(env->regs[0]); /* XXX */ +-} + + #define USE_ELF_CORE_DUMP + #define ELF_EXEC_PAGESIZE 4096 + +-enum +-{ +- ARM_HWCAP_ARM_SWP = 1 << 0, +- ARM_HWCAP_ARM_HALF = 1 << 1, +- ARM_HWCAP_ARM_THUMB = 1 << 2, +- ARM_HWCAP_ARM_26BIT = 1 << 3, +- ARM_HWCAP_ARM_FAST_MULT = 1 << 4, +- ARM_HWCAP_ARM_FPA = 1 << 5, +- ARM_HWCAP_ARM_VFP = 1 << 6, +- ARM_HWCAP_ARM_EDSP = 1 << 7, +- ARM_HWCAP_ARM_JAVA = 1 << 8, +- ARM_HWCAP_ARM_IWMMXT = 1 << 9, +- ARM_HWCAP_ARM_CRUNCH = 1 << 10, +- ARM_HWCAP_ARM_THUMBEE = 1 << 11, +- ARM_HWCAP_ARM_NEON = 1 << 12, +- ARM_HWCAP_ARM_VFPv3 = 1 << 13, +- ARM_HWCAP_ARM_VFPv3D16 = 1 << 14, +- ARM_HWCAP_ARM_TLS = 1 << 15, +- ARM_HWCAP_ARM_VFPv4 = 1 << 16, +- ARM_HWCAP_ARM_IDIVA = 1 << 17, +- ARM_HWCAP_ARM_IDIVT = 1 << 18, +- ARM_HWCAP_ARM_VFPD32 = 1 << 19, +- ARM_HWCAP_ARM_LPAE = 1 << 20, +- ARM_HWCAP_ARM_EVTSTRM = 1 << 21, +-}; +- +-enum { +- ARM_HWCAP2_ARM_AES = 1 << 0, +- ARM_HWCAP2_ARM_PMULL = 1 << 1, +- ARM_HWCAP2_ARM_SHA1 = 1 << 2, +- ARM_HWCAP2_ARM_SHA2 = 1 << 3, +- ARM_HWCAP2_ARM_CRC32 = 1 << 4, +-}; +- +-/* The commpage only exists for 32 bit kernels */ +- +-#define TARGET_HAS_VALIDATE_GUEST_SPACE +-/* Return 1 if the proposed guest space is suitable for the guest. +- * Return 0 if the proposed guest space isn't suitable, but another +- * address space should be tried. +- * Return -1 if there is no way the proposed guest space can be +- * valid regardless of the base. +- * The guest code may leave a page mapped and populate it if the +- * address is suitable. +- */ +-static int validate_guest_space(unsigned long guest_base, +- unsigned long guest_size) +-{ +- unsigned long real_start, test_page_addr; +- +- /* We need to check that we can force a fault on access to the +- * commpage at 0xffff0fxx +- */ +- test_page_addr = guest_base + (0xffff0f00 & qemu_host_page_mask); +- +- /* If the commpage lies within the already allocated guest space, +- * then there is no way we can allocate it. +- */ +- if (test_page_addr >= guest_base +- && test_page_addr <= (guest_base + guest_size)) { +- return -1; +- } +- +- /* Note it needs to be writeable to let us initialise it */ +- real_start = (unsigned long) +- mmap((void *)test_page_addr, qemu_host_page_size, +- PROT_READ | PROT_WRITE, +- MAP_ANONYMOUS | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); +- +- /* If we can't map it then try another address */ +- if (real_start == -1ul) { +- return 0; +- } +- +- if (real_start != test_page_addr) { +- /* OS didn't put the page where we asked - unmap and reject */ +- munmap((void *)real_start, qemu_host_page_size); +- return 0; +- } +- +- /* Leave the page mapped +- * Populate it (mmap should have left it all 0'd) +- */ +- +- /* Kernel helper versions */ +- __put_user(5, (uint32_t *)g2h(0xffff0ffcul)); +- +- /* Now it's populated make it RO */ +- if (mprotect((void *)test_page_addr, qemu_host_page_size, PROT_READ)) { +- perror("Protecting guest commpage"); +- exit(-1); +- } +- +- return 1; /* All good */ +-} +- +-#define ELF_HWCAP get_elf_hwcap() +-#define ELF_HWCAP2 get_elf_hwcap2() +- +-static uint32_t get_elf_hwcap(void) +-{ +- ARMCPU *cpu = ARM_CPU(thread_cpu); +- uint32_t hwcaps = 0; +- +- hwcaps |= ARM_HWCAP_ARM_SWP; +- hwcaps |= ARM_HWCAP_ARM_HALF; +- hwcaps |= ARM_HWCAP_ARM_THUMB; +- hwcaps |= ARM_HWCAP_ARM_FAST_MULT; +- +- /* probe for the extra features */ +-#define GET_FEATURE(feat, hwcap) \ +- do { if (arm_feature(&cpu->env, feat)) { hwcaps |= hwcap; } } while (0) +- /* EDSP is in v5TE and above, but all our v5 CPUs are v5TE */ +- GET_FEATURE(ARM_FEATURE_V5, ARM_HWCAP_ARM_EDSP); +- GET_FEATURE(ARM_FEATURE_VFP, ARM_HWCAP_ARM_VFP); +- GET_FEATURE(ARM_FEATURE_IWMMXT, ARM_HWCAP_ARM_IWMMXT); +- GET_FEATURE(ARM_FEATURE_THUMB2EE, ARM_HWCAP_ARM_THUMBEE); +- GET_FEATURE(ARM_FEATURE_NEON, ARM_HWCAP_ARM_NEON); +- GET_FEATURE(ARM_FEATURE_VFP3, ARM_HWCAP_ARM_VFPv3); +- GET_FEATURE(ARM_FEATURE_V6K, ARM_HWCAP_ARM_TLS); +- GET_FEATURE(ARM_FEATURE_VFP4, ARM_HWCAP_ARM_VFPv4); +- GET_FEATURE(ARM_FEATURE_ARM_DIV, ARM_HWCAP_ARM_IDIVA); +- GET_FEATURE(ARM_FEATURE_THUMB_DIV, ARM_HWCAP_ARM_IDIVT); +- /* All QEMU's VFPv3 CPUs have 32 registers, see VFP_DREG in translate.c. +- * Note that the ARM_HWCAP_ARM_VFPv3D16 bit is always the inverse of +- * ARM_HWCAP_ARM_VFPD32 (and so always clear for QEMU); it is unrelated +- * to our VFP_FP16 feature bit. +- */ +- GET_FEATURE(ARM_FEATURE_VFP3, ARM_HWCAP_ARM_VFPD32); +- GET_FEATURE(ARM_FEATURE_LPAE, ARM_HWCAP_ARM_LPAE); +- +- return hwcaps; +-} +- +-static uint32_t get_elf_hwcap2(void) +-{ +- ARMCPU *cpu = ARM_CPU(thread_cpu); +- uint32_t hwcaps = 0; +- +- GET_FEATURE(ARM_FEATURE_V8_AES, ARM_HWCAP2_ARM_AES); +- GET_FEATURE(ARM_FEATURE_V8_PMULL, ARM_HWCAP2_ARM_PMULL); +- GET_FEATURE(ARM_FEATURE_V8_SHA1, ARM_HWCAP2_ARM_SHA1); +- GET_FEATURE(ARM_FEATURE_V8_SHA256, ARM_HWCAP2_ARM_SHA2); +- GET_FEATURE(ARM_FEATURE_CRC, ARM_HWCAP2_ARM_CRC32); +- return hwcaps; +-} +- +-#undef GET_FEATURE +- +-#else +-/* 64 bit ARM definitions */ +-#define ELF_START_MMAP 0x80000000 +- +-#define elf_check_arch(x) ((x) == ELF_MACHINE) +- +-#define ELF_ARCH ELF_MACHINE +-#define ELF_CLASS ELFCLASS64 +-#define ELF_PLATFORM "aarch64" +- +-static inline void init_thread(struct target_pt_regs *regs, +- struct image_info *infop) +-{ +- abi_long stack = infop->start_stack; +- memset(regs, 0, sizeof(*regs)); +- +- regs->pc = infop->entry & ~0x3ULL; +- regs->sp = stack; +-} +- +-#define ELF_NREG 34 +-typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; +- +-static void elf_core_copy_regs(target_elf_gregset_t *regs, +- const CPUARMState *env) +-{ +- int i; +- +- for (i = 0; i < 32; i++) { +- (*regs)[i] = tswapreg(env->xregs[i]); +- } +- (*regs)[32] = tswapreg(env->pc); +- (*regs)[33] = tswapreg(pstate_read((CPUARMState *)env)); +-} +- +-#define USE_ELF_CORE_DUMP +-#define ELF_EXEC_PAGESIZE 4096 +- +-enum { +- ARM_HWCAP_A64_FP = 1 << 0, +- ARM_HWCAP_A64_ASIMD = 1 << 1, +- ARM_HWCAP_A64_EVTSTRM = 1 << 2, +- ARM_HWCAP_A64_AES = 1 << 3, +- ARM_HWCAP_A64_PMULL = 1 << 4, +- ARM_HWCAP_A64_SHA1 = 1 << 5, +- ARM_HWCAP_A64_SHA2 = 1 << 6, +- ARM_HWCAP_A64_CRC32 = 1 << 7, +-}; +- +-#define ELF_HWCAP get_elf_hwcap() +- +-static uint32_t get_elf_hwcap(void) +-{ +- ARMCPU *cpu = ARM_CPU(thread_cpu); +- uint32_t hwcaps = 0; +- +- hwcaps |= ARM_HWCAP_A64_FP; +- hwcaps |= ARM_HWCAP_A64_ASIMD; +- +- /* probe for the extra features */ +-#define GET_FEATURE(feat, hwcap) \ +- do { if (arm_feature(&cpu->env, feat)) { hwcaps |= hwcap; } } while (0) +- GET_FEATURE(ARM_FEATURE_V8_AES, ARM_HWCAP_A64_AES); +- GET_FEATURE(ARM_FEATURE_V8_PMULL, ARM_HWCAP_A64_PMULL); +- GET_FEATURE(ARM_FEATURE_V8_SHA1, ARM_HWCAP_A64_SHA1); +- GET_FEATURE(ARM_FEATURE_V8_SHA256, ARM_HWCAP_A64_SHA2); +- GET_FEATURE(ARM_FEATURE_CRC, ARM_HWCAP_A64_CRC32); +-#undef GET_FEATURE +- +- return hwcaps; +-} +- +-#endif /* not TARGET_AARCH64 */ +-#endif /* TARGET_ARM */ +- +-#ifdef TARGET_UNICORE32 +- +-#define ELF_START_MMAP 0x80000000 +- +-#define elf_check_arch(x) ((x) == EM_UNICORE32) +- +-#define ELF_CLASS ELFCLASS32 +-#define ELF_DATA ELFDATA2LSB +-#define ELF_ARCH EM_UNICORE32 +- +-static inline void init_thread(struct target_pt_regs *regs, +- struct image_info *infop) +-{ +- abi_long stack = infop->start_stack; +- memset(regs, 0, sizeof(*regs)); +- regs->UC32_REG_asr = 0x10; +- regs->UC32_REG_pc = infop->entry & 0xfffffffe; +- regs->UC32_REG_sp = infop->start_stack; +- /* FIXME - what to for failure of get_user()? */ +- get_user_ual(regs->UC32_REG_02, stack + 8); /* envp */ +- get_user_ual(regs->UC32_REG_01, stack + 4); /* envp */ +- /* XXX: it seems that r0 is zeroed after ! */ +- regs->UC32_REG_00 = 0; +-} +- +-#define ELF_NREG 34 +-typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; +- +-static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUUniCore32State *env) +-{ +- (*regs)[0] = env->regs[0]; +- (*regs)[1] = env->regs[1]; +- (*regs)[2] = env->regs[2]; +- (*regs)[3] = env->regs[3]; +- (*regs)[4] = env->regs[4]; +- (*regs)[5] = env->regs[5]; +- (*regs)[6] = env->regs[6]; +- (*regs)[7] = env->regs[7]; +- (*regs)[8] = env->regs[8]; +- (*regs)[9] = env->regs[9]; +- (*regs)[10] = env->regs[10]; +- (*regs)[11] = env->regs[11]; +- (*regs)[12] = env->regs[12]; +- (*regs)[13] = env->regs[13]; +- (*regs)[14] = env->regs[14]; +- (*regs)[15] = env->regs[15]; +- (*regs)[16] = env->regs[16]; +- (*regs)[17] = env->regs[17]; +- (*regs)[18] = env->regs[18]; +- (*regs)[19] = env->regs[19]; +- (*regs)[20] = env->regs[20]; +- (*regs)[21] = env->regs[21]; +- (*regs)[22] = env->regs[22]; +- (*regs)[23] = env->regs[23]; +- (*regs)[24] = env->regs[24]; +- (*regs)[25] = env->regs[25]; +- (*regs)[26] = env->regs[26]; +- (*regs)[27] = env->regs[27]; +- (*regs)[28] = env->regs[28]; +- (*regs)[29] = env->regs[29]; +- (*regs)[30] = env->regs[30]; +- (*regs)[31] = env->regs[31]; +- +- (*regs)[32] = cpu_asr_read((CPUUniCore32State *)env); +- (*regs)[33] = env->regs[0]; /* XXX */ +-} +- +-#define USE_ELF_CORE_DUMP +-#define ELF_EXEC_PAGESIZE 4096 +- +-#define ELF_HWCAP (UC32_HWCAP_CMOV | UC32_HWCAP_UCF64) +- +-#endif +- +-#ifdef TARGET_SPARC +-#ifdef TARGET_SPARC64 +- +-#define ELF_START_MMAP 0x80000000 +-#define ELF_HWCAP (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | HWCAP_SPARC_SWAP \ +- | HWCAP_SPARC_MULDIV | HWCAP_SPARC_V9) +-#ifndef TARGET_ABI32 +-#define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS ) +-#else +-#define elf_check_arch(x) ( (x) == EM_SPARC32PLUS || (x) == EM_SPARC ) +-#endif +- +-#define ELF_CLASS ELFCLASS64 +-#define ELF_ARCH EM_SPARCV9 +- +-#define STACK_BIAS 2047 +- +-static inline void init_thread(struct target_pt_regs *regs, +- struct image_info *infop) +-{ +-#ifndef TARGET_ABI32 +- regs->tstate = 0; +-#endif +- regs->pc = infop->entry; +- regs->npc = regs->pc + 4; +- regs->y = 0; +-#ifdef TARGET_ABI32 +- regs->u_regs[14] = infop->start_stack - 16 * 4; +-#else +- if (personality(infop->personality) == PER_LINUX32) +- regs->u_regs[14] = infop->start_stack - 16 * 4; +- else +- regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS; +-#endif +-} +- +-#else +-#define ELF_START_MMAP 0x80000000 +-#define ELF_HWCAP (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | HWCAP_SPARC_SWAP \ +- | HWCAP_SPARC_MULDIV) +-#define elf_check_arch(x) ( (x) == EM_SPARC ) +- +-#define ELF_CLASS ELFCLASS32 +-#define ELF_ARCH EM_SPARC +- +-static inline void init_thread(struct target_pt_regs *regs, +- struct image_info *infop) +-{ +- regs->psr = 0; +- regs->pc = infop->entry; +- regs->npc = regs->pc + 4; +- regs->y = 0; +- regs->u_regs[14] = infop->start_stack - 16 * 4; +-} +- +-#endif +-#endif +- +-#ifdef TARGET_PPC +- +-#define ELF_START_MMAP 0x80000000 +- +-#if defined(TARGET_PPC64) && !defined(TARGET_ABI32) +- +-#define elf_check_arch(x) ( (x) == EM_PPC64 ) +- +-#define ELF_CLASS ELFCLASS64 +- +-#else +- +-#define elf_check_arch(x) ( (x) == EM_PPC ) +- +-#define ELF_CLASS ELFCLASS32 +- +-#endif +- +-#define ELF_ARCH EM_PPC +- +-/* Feature masks for the Aux Vector Hardware Capabilities (AT_HWCAP). +- See arch/powerpc/include/asm/cputable.h. */ +-enum { +- QEMU_PPC_FEATURE_32 = 0x80000000, +- QEMU_PPC_FEATURE_64 = 0x40000000, +- QEMU_PPC_FEATURE_601_INSTR = 0x20000000, +- QEMU_PPC_FEATURE_HAS_ALTIVEC = 0x10000000, +- QEMU_PPC_FEATURE_HAS_FPU = 0x08000000, +- QEMU_PPC_FEATURE_HAS_MMU = 0x04000000, +- QEMU_PPC_FEATURE_HAS_4xxMAC = 0x02000000, +- QEMU_PPC_FEATURE_UNIFIED_CACHE = 0x01000000, +- QEMU_PPC_FEATURE_HAS_SPE = 0x00800000, +- QEMU_PPC_FEATURE_HAS_EFP_SINGLE = 0x00400000, +- QEMU_PPC_FEATURE_HAS_EFP_DOUBLE = 0x00200000, +- QEMU_PPC_FEATURE_NO_TB = 0x00100000, +- QEMU_PPC_FEATURE_POWER4 = 0x00080000, +- QEMU_PPC_FEATURE_POWER5 = 0x00040000, +- QEMU_PPC_FEATURE_POWER5_PLUS = 0x00020000, +- QEMU_PPC_FEATURE_CELL = 0x00010000, +- QEMU_PPC_FEATURE_BOOKE = 0x00008000, +- QEMU_PPC_FEATURE_SMT = 0x00004000, +- QEMU_PPC_FEATURE_ICACHE_SNOOP = 0x00002000, +- QEMU_PPC_FEATURE_ARCH_2_05 = 0x00001000, +- QEMU_PPC_FEATURE_PA6T = 0x00000800, +- QEMU_PPC_FEATURE_HAS_DFP = 0x00000400, +- QEMU_PPC_FEATURE_POWER6_EXT = 0x00000200, +- QEMU_PPC_FEATURE_ARCH_2_06 = 0x00000100, +- QEMU_PPC_FEATURE_HAS_VSX = 0x00000080, +- QEMU_PPC_FEATURE_PSERIES_PERFMON_COMPAT = 0x00000040, +- +- QEMU_PPC_FEATURE_TRUE_LE = 0x00000002, +- QEMU_PPC_FEATURE_PPC_LE = 0x00000001, +- +- /* Feature definitions in AT_HWCAP2. */ +- QEMU_PPC_FEATURE2_ARCH_2_07 = 0x80000000, /* ISA 2.07 */ +- QEMU_PPC_FEATURE2_HAS_HTM = 0x40000000, /* Hardware Transactional Memory */ +- QEMU_PPC_FEATURE2_HAS_DSCR = 0x20000000, /* Data Stream Control Register */ +- QEMU_PPC_FEATURE2_HAS_EBB = 0x10000000, /* Event Base Branching */ +- QEMU_PPC_FEATURE2_HAS_ISEL = 0x08000000, /* Integer Select */ +- QEMU_PPC_FEATURE2_HAS_TAR = 0x04000000, /* Target Address Register */ +-}; +- +-#define ELF_HWCAP get_elf_hwcap() +- +-static uint32_t get_elf_hwcap(void) +-{ +- PowerPCCPU *cpu = POWERPC_CPU(thread_cpu); +- uint32_t features = 0; +- +- /* We don't have to be terribly complete here; the high points are +- Altivec/FP/SPE support. Anything else is just a bonus. */ +-#define GET_FEATURE(flag, feature) \ +- do { if (cpu->env.insns_flags & flag) { features |= feature; } } while (0) +-#define GET_FEATURE2(flag, feature) \ +- do { if (cpu->env.insns_flags2 & flag) { features |= feature; } } while (0) +- GET_FEATURE(PPC_64B, QEMU_PPC_FEATURE_64); +- GET_FEATURE(PPC_FLOAT, QEMU_PPC_FEATURE_HAS_FPU); +- GET_FEATURE(PPC_ALTIVEC, QEMU_PPC_FEATURE_HAS_ALTIVEC); +- GET_FEATURE(PPC_SPE, QEMU_PPC_FEATURE_HAS_SPE); +- GET_FEATURE(PPC_SPE_SINGLE, QEMU_PPC_FEATURE_HAS_EFP_SINGLE); +- GET_FEATURE(PPC_SPE_DOUBLE, QEMU_PPC_FEATURE_HAS_EFP_DOUBLE); +- GET_FEATURE(PPC_BOOKE, QEMU_PPC_FEATURE_BOOKE); +- GET_FEATURE(PPC_405_MAC, QEMU_PPC_FEATURE_HAS_4xxMAC); +- GET_FEATURE2(PPC2_DFP, QEMU_PPC_FEATURE_HAS_DFP); +- GET_FEATURE2(PPC2_VSX, QEMU_PPC_FEATURE_HAS_VSX); +- GET_FEATURE2((PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 | PPC2_ATOMIC_ISA206 | +- PPC2_FP_CVT_ISA206 | PPC2_FP_TST_ISA206), +- QEMU_PPC_FEATURE_ARCH_2_06); +-#undef GET_FEATURE +-#undef GET_FEATURE2 +- +- return features; +-} +- +-#define ELF_HWCAP2 get_elf_hwcap2() +- +-static uint32_t get_elf_hwcap2(void) +-{ +- PowerPCCPU *cpu = POWERPC_CPU(thread_cpu); +- uint32_t features = 0; +- +-#define GET_FEATURE(flag, feature) \ +- do { if (cpu->env.insns_flags & flag) { features |= feature; } } while (0) +-#define GET_FEATURE2(flag, feature) \ +- do { if (cpu->env.insns_flags2 & flag) { features |= feature; } } while (0) +- +- GET_FEATURE(PPC_ISEL, QEMU_PPC_FEATURE2_HAS_ISEL); +- GET_FEATURE2(PPC2_BCTAR_ISA207, QEMU_PPC_FEATURE2_HAS_TAR); +- GET_FEATURE2((PPC2_BCTAR_ISA207 | PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 | +- PPC2_ISA207S), QEMU_PPC_FEATURE2_ARCH_2_07); +- +-#undef GET_FEATURE +-#undef GET_FEATURE2 +- +- return features; +-} +- +-/* +- * The requirements here are: +- * - keep the final alignment of sp (sp & 0xf) +- * - make sure the 32-bit value at the first 16 byte aligned position of +- * AUXV is greater than 16 for glibc compatibility. +- * AT_IGNOREPPC is used for that. +- * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC, +- * even if DLINFO_ARCH_ITEMS goes to zero or is undefined. +- */ +-#define DLINFO_ARCH_ITEMS 5 +-#define ARCH_DLINFO \ +- do { \ +- PowerPCCPU *cpu = POWERPC_CPU(thread_cpu); \ +- NEW_AUX_ENT(AT_DCACHEBSIZE, cpu->env.dcache_line_size); \ +- NEW_AUX_ENT(AT_ICACHEBSIZE, cpu->env.icache_line_size); \ +- NEW_AUX_ENT(AT_UCACHEBSIZE, 0); \ +- /* \ +- * Now handle glibc compatibility. \ +- */ \ +- NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ +- NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ +- } while (0) +- +-static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop) +-{ +- _regs->gpr[1] = infop->start_stack; +-#if defined(TARGET_PPC64) && !defined(TARGET_ABI32) +- if (get_ppc64_abi(infop) < 2) { +- uint64_t val; +- get_user_u64(val, infop->entry + 8); +- _regs->gpr[2] = val + infop->load_bias; +- get_user_u64(val, infop->entry); +- infop->entry = val + infop->load_bias; +- } else { +- _regs->gpr[12] = infop->entry; /* r12 set to global entry address */ +- } +-#endif +- _regs->nip = infop->entry; +-} +- +-/* See linux kernel: arch/powerpc/include/asm/elf.h. */ +-#define ELF_NREG 48 +-typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; +- +-static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *env) +-{ +- int i; +- target_ulong ccr = 0; +- +- for (i = 0; i < ARRAY_SIZE(env->gpr); i++) { +- (*regs)[i] = tswapreg(env->gpr[i]); +- } +- +- (*regs)[32] = tswapreg(env->nip); +- (*regs)[33] = tswapreg(env->msr); +- (*regs)[35] = tswapreg(env->ctr); +- (*regs)[36] = tswapreg(env->lr); +- (*regs)[37] = tswapreg(env->xer); +- +- for (i = 0; i < ARRAY_SIZE(env->crf); i++) { +- ccr |= env->crf[i] << (32 - ((i + 1) * 4)); +- } +- (*regs)[38] = tswapreg(ccr); +-} +- +-#define USE_ELF_CORE_DUMP +-#define ELF_EXEC_PAGESIZE 4096 +- +-#endif +- +-#ifdef TARGET_MIPS +- +-#define ELF_START_MMAP 0x80000000 +- +-#define elf_check_arch(x) ( (x) == EM_MIPS ) +- +-#ifdef TARGET_MIPS64 +-#define ELF_CLASS ELFCLASS64 +-#else +-#define ELF_CLASS ELFCLASS32 +-#endif +-#define ELF_ARCH EM_MIPS +- +-static inline void init_thread(struct target_pt_regs *regs, +- struct image_info *infop) +-{ +- regs->cp0_status = 2 << CP0St_KSU; +- regs->cp0_epc = infop->entry; +- regs->regs[29] = infop->start_stack; +-} +- +-/* See linux kernel: arch/mips/include/asm/elf.h. */ +-#define ELF_NREG 45 +-typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; +- +-/* See linux kernel: arch/mips/include/asm/reg.h. */ +-enum { +-#ifdef TARGET_MIPS64 +- TARGET_EF_R0 = 0, +-#else +- TARGET_EF_R0 = 6, +-#endif +- TARGET_EF_R26 = TARGET_EF_R0 + 26, +- TARGET_EF_R27 = TARGET_EF_R0 + 27, +- TARGET_EF_LO = TARGET_EF_R0 + 32, +- TARGET_EF_HI = TARGET_EF_R0 + 33, +- TARGET_EF_CP0_EPC = TARGET_EF_R0 + 34, +- TARGET_EF_CP0_BADVADDR = TARGET_EF_R0 + 35, +- TARGET_EF_CP0_STATUS = TARGET_EF_R0 + 36, +- TARGET_EF_CP0_CAUSE = TARGET_EF_R0 + 37 +-}; +- +-/* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs. */ +-static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMIPSState *env) +-{ +- int i; +- +- for (i = 0; i < TARGET_EF_R0; i++) { +- (*regs)[i] = 0; +- } +- (*regs)[TARGET_EF_R0] = 0; +- +- for (i = 1; i < ARRAY_SIZE(env->active_tc.gpr); i++) { +- (*regs)[TARGET_EF_R0 + i] = tswapreg(env->active_tc.gpr[i]); +- } +- +- (*regs)[TARGET_EF_R26] = 0; +- (*regs)[TARGET_EF_R27] = 0; +- (*regs)[TARGET_EF_LO] = tswapreg(env->active_tc.LO[0]); +- (*regs)[TARGET_EF_HI] = tswapreg(env->active_tc.HI[0]); +- (*regs)[TARGET_EF_CP0_EPC] = tswapreg(env->active_tc.PC); +- (*regs)[TARGET_EF_CP0_BADVADDR] = tswapreg(env->CP0_BadVAddr); +- (*regs)[TARGET_EF_CP0_STATUS] = tswapreg(env->CP0_Status); +- (*regs)[TARGET_EF_CP0_CAUSE] = tswapreg(env->CP0_Cause); +-} +- +-#define USE_ELF_CORE_DUMP +-#define ELF_EXEC_PAGESIZE 4096 +- +-#endif /* TARGET_MIPS */ +- +-#ifdef TARGET_MICROBLAZE +- +-#define ELF_START_MMAP 0x80000000 +- +-#define elf_check_arch(x) ( (x) == EM_MICROBLAZE || (x) == EM_MICROBLAZE_OLD) +- +-#define ELF_CLASS ELFCLASS32 +-#define ELF_ARCH EM_MICROBLAZE +- +-static inline void init_thread(struct target_pt_regs *regs, +- struct image_info *infop) +-{ +- regs->pc = infop->entry; +- regs->r1 = infop->start_stack; +- +-} +- +-#define ELF_EXEC_PAGESIZE 4096 +- +-#define USE_ELF_CORE_DUMP +-#define ELF_NREG 38 +-typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; +- +-/* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs. */ +-static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMBState *env) +-{ +- int i, pos = 0; +- +- for (i = 0; i < 32; i++) { +- (*regs)[pos++] = tswapreg(env->regs[i]); +- } +- +- for (i = 0; i < 6; i++) { +- (*regs)[pos++] = tswapreg(env->sregs[i]); +- } +-} +- +-#endif /* TARGET_MICROBLAZE */ +- +-#ifdef TARGET_OPENRISC +- +-#define ELF_START_MMAP 0x08000000 +- +-#define elf_check_arch(x) ((x) == EM_OPENRISC) +- +-#define ELF_ARCH EM_OPENRISC +-#define ELF_CLASS ELFCLASS32 +-#define ELF_DATA ELFDATA2MSB +- +-static inline void init_thread(struct target_pt_regs *regs, +- struct image_info *infop) +-{ +- regs->pc = infop->entry; +- regs->gpr[1] = infop->start_stack; +-} +- +-#define USE_ELF_CORE_DUMP +-#define ELF_EXEC_PAGESIZE 8192 +- +-/* See linux kernel arch/openrisc/include/asm/elf.h. */ +-#define ELF_NREG 34 /* gprs and pc, sr */ +-typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; + +-static void elf_core_copy_regs(target_elf_gregset_t *regs, +- const CPUOpenRISCState *env) +-{ +- int i; +- +- for (i = 0; i < 32; i++) { +- (*regs)[i] = tswapreg(env->gpr[i]); +- } +- +- (*regs)[32] = tswapreg(env->pc); +- (*regs)[33] = tswapreg(env->sr); +-} +-#define ELF_HWCAP 0 +-#define ELF_PLATFORM NULL +- +-#endif /* TARGET_OPENRISC */ +- +-#ifdef TARGET_SH4 +- +-#define ELF_START_MMAP 0x80000000 +- +-#define elf_check_arch(x) ( (x) == EM_SH ) +- +-#define ELF_CLASS ELFCLASS32 +-#define ELF_ARCH EM_SH +- +-static inline void init_thread(struct target_pt_regs *regs, +- struct image_info *infop) +-{ +- /* Check other registers XXXXX */ +- regs->pc = infop->entry; +- regs->regs[15] = infop->start_stack; +-} +- +-/* See linux kernel: arch/sh/include/asm/elf.h. */ +-#define ELF_NREG 23 +-typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; +- +-/* See linux kernel: arch/sh/include/asm/ptrace.h. */ +-enum { +- TARGET_REG_PC = 16, +- TARGET_REG_PR = 17, +- TARGET_REG_SR = 18, +- TARGET_REG_GBR = 19, +- TARGET_REG_MACH = 20, +- TARGET_REG_MACL = 21, +- TARGET_REG_SYSCALL = 22 +-}; +- +-static inline void elf_core_copy_regs(target_elf_gregset_t *regs, +- const CPUSH4State *env) +-{ +- int i; +- +- for (i = 0; i < 16; i++) { +- (*regs[i]) = tswapreg(env->gregs[i]); +- } +- +- (*regs)[TARGET_REG_PC] = tswapreg(env->pc); +- (*regs)[TARGET_REG_PR] = tswapreg(env->pr); +- (*regs)[TARGET_REG_SR] = tswapreg(env->sr); +- (*regs)[TARGET_REG_GBR] = tswapreg(env->gbr); +- (*regs)[TARGET_REG_MACH] = tswapreg(env->mach); +- (*regs)[TARGET_REG_MACL] = tswapreg(env->macl); +- (*regs)[TARGET_REG_SYSCALL] = 0; /* FIXME */ +-} +- +-#define USE_ELF_CORE_DUMP +-#define ELF_EXEC_PAGESIZE 4096 +- +-#endif +- +-#ifdef TARGET_CRIS +- +-#define ELF_START_MMAP 0x80000000 +- +-#define elf_check_arch(x) ( (x) == EM_CRIS ) +- +-#define ELF_CLASS ELFCLASS32 +-#define ELF_ARCH EM_CRIS +- +-static inline void init_thread(struct target_pt_regs *regs, +- struct image_info *infop) +-{ +- regs->erp = infop->entry; +-} +- +-#define ELF_EXEC_PAGESIZE 8192 +- +-#endif +- +-#ifdef TARGET_M68K +- +-#define ELF_START_MMAP 0x80000000 +- +-#define elf_check_arch(x) ( (x) == EM_68K ) +- +-#define ELF_CLASS ELFCLASS32 +-#define ELF_ARCH EM_68K +- +-/* ??? Does this need to do anything? +- #define ELF_PLAT_INIT(_r) */ +- +-static inline void init_thread(struct target_pt_regs *regs, +- struct image_info *infop) +-{ +- regs->usp = infop->start_stack; +- regs->sr = 0; +- regs->pc = infop->entry; +-} +- +-/* See linux kernel: arch/m68k/include/asm/elf.h. */ +-#define ELF_NREG 20 +-typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; +- +-static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUM68KState *env) +-{ +- (*regs)[0] = tswapreg(env->dregs[1]); +- (*regs)[1] = tswapreg(env->dregs[2]); +- (*regs)[2] = tswapreg(env->dregs[3]); +- (*regs)[3] = tswapreg(env->dregs[4]); +- (*regs)[4] = tswapreg(env->dregs[5]); +- (*regs)[5] = tswapreg(env->dregs[6]); +- (*regs)[6] = tswapreg(env->dregs[7]); +- (*regs)[7] = tswapreg(env->aregs[0]); +- (*regs)[8] = tswapreg(env->aregs[1]); +- (*regs)[9] = tswapreg(env->aregs[2]); +- (*regs)[10] = tswapreg(env->aregs[3]); +- (*regs)[11] = tswapreg(env->aregs[4]); +- (*regs)[12] = tswapreg(env->aregs[5]); +- (*regs)[13] = tswapreg(env->aregs[6]); +- (*regs)[14] = tswapreg(env->dregs[0]); +- (*regs)[15] = tswapreg(env->aregs[7]); +- (*regs)[16] = tswapreg(env->dregs[0]); /* FIXME: orig_d0 */ +- (*regs)[17] = tswapreg(env->sr); +- (*regs)[18] = tswapreg(env->pc); +- (*regs)[19] = 0; /* FIXME: regs->format | regs->vector */ +-} +- +-#define USE_ELF_CORE_DUMP +-#define ELF_EXEC_PAGESIZE 8192 +- +-#endif +- +-#ifdef TARGET_ALPHA +- +-#define ELF_START_MMAP (0x30000000000ULL) +- +-#define elf_check_arch(x) ( (x) == ELF_ARCH ) +- +-#define ELF_CLASS ELFCLASS64 +-#define ELF_ARCH EM_ALPHA +- +-static inline void init_thread(struct target_pt_regs *regs, +- struct image_info *infop) +-{ +- regs->pc = infop->entry; +- regs->ps = 8; +- regs->usp = infop->start_stack; +-} +- +-#define ELF_EXEC_PAGESIZE 8192 +- +-#endif /* TARGET_ALPHA */ +- +-#ifdef TARGET_S390X +- +-#define ELF_START_MMAP (0x20000000000ULL) +- +-#define elf_check_arch(x) ( (x) == ELF_ARCH ) +- +-#define ELF_CLASS ELFCLASS64 +-#define ELF_DATA ELFDATA2MSB +-#define ELF_ARCH EM_S390 +- +-static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) +-{ +- regs->psw.addr = infop->entry; +- regs->psw.mask = PSW_MASK_64 | PSW_MASK_32; +- regs->gprs[15] = infop->start_stack; +-} +- +-#endif /* TARGET_S390X */ +- +-#ifndef ELF_PLATFORM +-#define ELF_PLATFORM (NULL) +-#endif +- +-#ifndef ELF_HWCAP +-#define ELF_HWCAP 0 +-#endif + + #ifdef TARGET_ABI32 + #undef ELF_CLASS +@@ -1310,10 +251,11 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias); + This can be performed before bswapping the entire header. */ + static bool elf_check_ident(struct elfhdr *ehdr) + { +- return (ehdr->e_ident[EI_MAG0] == ELFMAG0 +- && ehdr->e_ident[EI_MAG1] == ELFMAG1 +- && ehdr->e_ident[EI_MAG2] == ELFMAG2 +- && ehdr->e_ident[EI_MAG3] == ELFMAG3 ++ return ( ++ (ehdr->e_ident[EI_MAG0] == ELFMAG0 || ehdr->e_ident[EI_MAG0] == CGCMAG0) ++ && (ehdr->e_ident[EI_MAG1] == ELFMAG1 || ehdr->e_ident[EI_MAG1] == CGCMAG1) ++ && (ehdr->e_ident[EI_MAG2] == ELFMAG2 || ehdr->e_ident[EI_MAG2] == CGCMAG2) ++ && (ehdr->e_ident[EI_MAG3] == ELFMAG3 || ehdr->e_ident[EI_MAG3] == CGCMAG3) + && ehdr->e_ident[EI_CLASS] == ELF_CLASS + && ehdr->e_ident[EI_DATA] == ELF_DATA + && ehdr->e_ident[EI_VERSION] == EV_CURRENT); +@@ -1329,101 +271,40 @@ static bool elf_check_ehdr(struct elfhdr *ehdr) + && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN)); + } + +-/* +- * 'copy_elf_strings()' copies argument/envelope strings from user +- * memory to free pages in kernel mem. These are in a format ready +- * to be put directly into the top of new user memory. +- * +- */ +-static abi_ulong copy_elf_strings(int argc,char ** argv, void **page, +- abi_ulong p) +-{ +- char *tmp, *tmp1, *pag = NULL; +- int len, offset = 0; +- +- if (!p) { +- return 0; /* bullet-proofing */ +- } +- while (argc-- > 0) { +- tmp = argv[argc]; +- if (!tmp) { +- fprintf(stderr, "VFS: argc is wrong"); +- exit(-1); +- } +- tmp1 = tmp; +- while (*tmp++); +- len = tmp - tmp1; +- if (p < len) { /* this shouldn't happen - 128kB */ +- return 0; +- } +- while (len) { +- --p; --tmp; --len; +- if (--offset < 0) { +- offset = p % TARGET_PAGE_SIZE; +- pag = (char *)page[p/TARGET_PAGE_SIZE]; +- if (!pag) { +- pag = g_try_malloc0(TARGET_PAGE_SIZE); +- page[p/TARGET_PAGE_SIZE] = pag; +- if (!pag) +- return 0; +- } +- } +- if (len == 0 || offset == 0) { +- *(pag + offset) = *tmp; +- } +- else { +- int bytes_to_copy = (len > offset) ? offset : len; +- tmp -= bytes_to_copy; +- p -= bytes_to_copy; +- offset -= bytes_to_copy; +- len -= bytes_to_copy; +- memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1); +- } +- } +- } +- return p; +-} + + static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm, + struct image_info *info) + { +- abi_ulong stack_base, size, error, guard; +- int i; ++ abi_ulong stack_base, size, error; + +- /* Create enough stack to hold everything. If we don't use +- it for args, we'll use it for something else. */ +- size = guest_stack_size; +- if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) { +- size = MAX_ARG_PAGES*TARGET_PAGE_SIZE; +- } +- guard = TARGET_PAGE_SIZE; +- if (guard < qemu_real_host_page_size) { +- guard = qemu_real_host_page_size; +- } ++ size = 33 * 0x1000; ++ ++ /* For some weird reason, they start the stack one dword ++ * below the top. Not sure if I understand why, there's ++ * nothing there and push would work anyway! ++ * Anyway, we need to force-align and then dis-align. */ ++ abi_ulong mmap_stack_top = CGC_INITIAL_SP - (size - 4); + +- error = target_mmap(0, size + guard, PROT_READ | PROT_WRITE, +- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); ++ /* top == lowest "allocated" address */ ++ cgc_stack_top = mmap_stack_top; ++ max_stack_top = CGC_INITIAL_SP - (guest_stack_size - 4); ++ assert((CGC_INITIAL_SP + 4 - max_stack_top)/1024/1024 == 8); ++ ++ /* Yeehaw, CGC binaries all have an executable stack */ ++ error = target_mmap(mmap_stack_top, size, PROT_READ | PROT_WRITE | PROT_EXEC, ++ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); + if (error == -1) { + perror("mmap stack"); + exit(-1); + } + +- /* We reserve one extra page at the top of the stack as guard. */ +- target_mprotect(error, guard, PROT_NONE); +- +- info->stack_limit = error + guard; +- stack_base = info->stack_limit + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE; ++ info->stack_limit = error; ++ stack_base = info->stack_limit + size - 4; /* de-align, as mandated */ + p += stack_base; + +- for (i = 0 ; i < MAX_ARG_PAGES ; i++) { +- if (bprm->page[i]) { +- info->rss++; +- /* FIXME - check return value of memcpy_to_target() for failure */ +- memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE); +- g_free(bprm->page[i]); +- } +- stack_base += TARGET_PAGE_SIZE; +- } ++ assert(stack_base == CGC_INITIAL_SP); ++ ++ /* We don't want to copy anything to the stack, it should be all zeroes */ + return p; + } + +@@ -1497,129 +378,6 @@ static abi_ulong loader_build_fdpic_loadmap(struct image_info *info, abi_ulong s + } + #endif + +-static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, +- struct elfhdr *exec, +- struct image_info *info, +- struct image_info *interp_info) +-{ +- abi_ulong sp; +- abi_ulong sp_auxv; +- int size; +- int i; +- abi_ulong u_rand_bytes; +- uint8_t k_rand_bytes[16]; +- abi_ulong u_platform; +- const char *k_platform; +- const int n = sizeof(elf_addr_t); +- +- sp = p; +- +-#ifdef CONFIG_USE_FDPIC +- /* Needs to be before we load the env/argc/... */ +- if (elf_is_fdpic(exec)) { +- /* Need 4 byte alignment for these structs */ +- sp &= ~3; +- sp = loader_build_fdpic_loadmap(info, sp); +- info->other_info = interp_info; +- if (interp_info) { +- interp_info->other_info = info; +- sp = loader_build_fdpic_loadmap(interp_info, sp); +- } +- } +-#endif +- +- u_platform = 0; +- k_platform = ELF_PLATFORM; +- if (k_platform) { +- size_t len = strlen(k_platform) + 1; +- sp -= (len + n - 1) & ~(n - 1); +- u_platform = sp; +- /* FIXME - check return value of memcpy_to_target() for failure */ +- memcpy_to_target(sp, k_platform, len); +- } +- +- /* +- * Generate 16 random bytes for userspace PRNG seeding (not +- * cryptically secure but it's not the aim of QEMU). +- */ +- for (i = 0; i < 16; i++) { +- k_rand_bytes[i] = rand(); +- } +- sp -= 16; +- u_rand_bytes = sp; +- /* FIXME - check return value of memcpy_to_target() for failure */ +- memcpy_to_target(sp, k_rand_bytes, 16); +- +- /* +- * Force 16 byte _final_ alignment here for generality. +- */ +- sp = sp &~ (abi_ulong)15; +- size = (DLINFO_ITEMS + 1) * 2; +- if (k_platform) +- size += 2; +-#ifdef DLINFO_ARCH_ITEMS +- size += DLINFO_ARCH_ITEMS * 2; +-#endif +-#ifdef ELF_HWCAP2 +- size += 2; +-#endif +- size += envc + argc + 2; +- size += 1; /* argc itself */ +- size *= n; +- if (size & 15) +- sp -= 16 - (size & 15); +- +- /* This is correct because Linux defines +- * elf_addr_t as Elf32_Off / Elf64_Off +- */ +-#define NEW_AUX_ENT(id, val) do { \ +- sp -= n; put_user_ual(val, sp); \ +- sp -= n; put_user_ual(id, sp); \ +- } while(0) +- +- sp_auxv = sp; +- NEW_AUX_ENT (AT_NULL, 0); +- +- /* There must be exactly DLINFO_ITEMS entries here. */ +- NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff)); +- NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr))); +- NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum)); +- NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(MAX(TARGET_PAGE_SIZE, getpagesize()))); +- NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_info ? interp_info->load_addr : 0)); +- NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0); +- NEW_AUX_ENT(AT_ENTRY, info->entry); +- NEW_AUX_ENT(AT_UID, (abi_ulong) getuid()); +- NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid()); +- NEW_AUX_ENT(AT_GID, (abi_ulong) getgid()); +- NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid()); +- NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP); +- NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK)); +- NEW_AUX_ENT(AT_RANDOM, (abi_ulong) u_rand_bytes); +- +-#ifdef ELF_HWCAP2 +- NEW_AUX_ENT(AT_HWCAP2, (abi_ulong) ELF_HWCAP2); +-#endif +- +- if (k_platform) +- NEW_AUX_ENT(AT_PLATFORM, u_platform); +-#ifdef ARCH_DLINFO +- /* +- * ARCH_DLINFO must come last so platform specific code can enforce +- * special alignment requirements on the AUXV if necessary (eg. PPC). +- */ +- ARCH_DLINFO; +-#endif +-#undef NEW_AUX_ENT +- +- info->saved_auxv = sp; +- info->auxv_len = sp_auxv - sp; +- +- sp = loader_build_argptr(envc, argc, sp, p, 0); +- /* Check the right amount of stack was allocated for auxvec, envp & argv. */ +- assert(sp_auxv - sp == size); +- return sp; +-} +- + #ifndef TARGET_HAS_VALIDATE_GUEST_SPACE + /* If the guest doesn't have a validation function just agree */ + static int validate_guest_space(unsigned long guest_base, +@@ -1889,6 +647,10 @@ static void load_elf_image(const char *image_name, int image_fd, + info->brk = 0; + info->elf_flags = ehdr->e_flags; + ++#ifdef AFL ++ if (!afl_entry_point) afl_entry_point = info->entry; ++#endif ++ + for (i = 0; i < ehdr->e_phnum; i++) { + struct elf_phdr *eppnt = phdr + i; + if (eppnt->p_type == PT_LOAD) { +@@ -1903,6 +665,11 @@ static void load_elf_image(const char *image_name, int image_fd, + vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr); + vaddr_ps = TARGET_ELF_PAGESTART(vaddr); + ++ /* CGC can insert empty segments and consequently the CGC ++ loader ignores them, we'll make that check here */ ++ if (eppnt->p_memsz == 0) ++ continue; ++ + error = target_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po, + elf_prot, MAP_PRIVATE | MAP_FIXED, + image_fd, eppnt->p_offset - vaddr_po); +@@ -1922,9 +689,15 @@ static void load_elf_image(const char *image_name, int image_fd, + if (elf_prot & PROT_EXEC) { + if (vaddr < info->start_code) { + info->start_code = vaddr; ++#ifdef AFL ++ if (!afl_start_code) afl_start_code = vaddr; ++#endif + } + if (vaddr_ef > info->end_code) { + info->end_code = vaddr_ef; ++#ifdef AFL ++ if (!afl_end_code) afl_end_code = vaddr_ef; ++#endif + } + } + if (elf_prot & PROT_WRITE) { +@@ -1993,31 +766,6 @@ static void load_elf_image(const char *image_name, int image_fd, + exit(-1); + } + +-static void load_elf_interp(const char *filename, struct image_info *info, +- char bprm_buf[BPRM_BUF_SIZE]) +-{ +- int fd, retval; +- +- fd = open(path(filename), O_RDONLY); +- if (fd < 0) { +- goto exit_perror; +- } +- +- retval = read(fd, bprm_buf, BPRM_BUF_SIZE); +- if (retval < 0) { +- goto exit_perror; +- } +- if (retval < BPRM_BUF_SIZE) { +- memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval); +- } +- +- load_elf_image(filename, fd, info, NULL, bprm_buf); +- return; +- +- exit_perror: +- fprintf(stderr, "%s: %s\n", filename, strerror(errno)); +- exit(-1); +-} + + static int symfind(const void *s0, const void *s1) + { +@@ -2165,22 +913,20 @@ give_up: + + int load_elf_binary(struct linux_binprm *bprm, struct image_info *info) + { +- struct image_info interp_info; +- struct elfhdr elf_ex; +- char *elf_interpreter = NULL; +- +- info->start_mmap = (abi_ulong)ELF_START_MMAP; ++ info->start_mmap = (abi_ulong)ELF_START_MMAP; /* Will be reset to reserved_va in main! */ + info->mmap = 0; + info->rss = 0; + + load_elf_image(bprm->filename, bprm->fd, info, +- &elf_interpreter, bprm->buf); ++ NULL /*elf_interpreter*/, bprm->buf); + + /* ??? We need a copy of the elf header for passing to create_elf_tables. + If we do nothing, we'll have overwritten this when we re-use bprm->buf + when we load the interpreter. */ +- elf_ex = *(struct elfhdr *)bprm->buf; ++ //elf_ex = *(struct elfhdr *)bprm->buf; + ++ /* Ignore the argc, argv, and envp, they aren't used in CGC */ ++ /* + bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p); + bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p); + bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p); +@@ -2188,43 +934,21 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info) + fprintf(stderr, "%s: %s\n", bprm->filename, strerror(E2BIG)); + exit(-1); + } ++ */ + + /* Do this so that we can load the interpreter, if need be. We will + change some of these later */ + bprm->p = setup_arg_pages(bprm->p, bprm, info); + +- if (elf_interpreter) { +- load_elf_interp(elf_interpreter, &interp_info, bprm->buf); +- +- /* If the program interpreter is one of these two, then assume +- an iBCS2 image. Otherwise assume a native linux image. */ +- +- if (strcmp(elf_interpreter, "/usr/lib/libc.so.1") == 0 +- || strcmp(elf_interpreter, "/usr/lib/ld.so.1") == 0) { +- info->personality = PER_SVR4; +- +- /* Why this, you ask??? Well SVr4 maps page 0 as read-only, +- and some applications "depend" upon this behavior. Since +- we do not have the power to recompile these, we emulate +- the SVr4 behavior. Sigh. */ +- target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC, +- MAP_FIXED | MAP_PRIVATE, -1, 0); +- } +- } + ++ /* CGC binaries obviously don't need ELF tables... */ ++ /* + bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &elf_ex, + info, (elf_interpreter ? &interp_info : NULL)); ++ */ ++ + info->start_stack = bprm->p; + +- /* If we have an interpreter, set that as the program's entry point. +- Copy the load_bias as well, to help PPC64 interpret the entry +- point as a function descriptor. Do this after creating elf tables +- so that we copy the original program entry point into the AUXV. */ +- if (elf_interpreter) { +- info->load_bias = interp_info.load_bias; +- info->entry = interp_info.entry; +- free(elf_interpreter); +- } + + #ifdef USE_ELF_CORE_DUMP + bprm->core_dump = &elf_core_dump; +@@ -2384,7 +1108,6 @@ static void fill_note(struct memelfnote *, const char *, int, + unsigned int, void *); + static void fill_prstatus(struct target_elf_prstatus *, const TaskState *, int); + static int fill_psinfo(struct target_elf_prpsinfo *, const TaskState *); +-static void fill_auxv_note(struct memelfnote *, const TaskState *); + static void fill_elf_note_phdr(struct elf_phdr *, int, off_t); + static size_t note_size(const struct memelfnote *); + static void free_note_info(struct elf_note_info *); +@@ -2661,27 +1384,6 @@ static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts) + return (0); + } + +-static void fill_auxv_note(struct memelfnote *note, const TaskState *ts) +-{ +- elf_addr_t auxv = (elf_addr_t)ts->info->saved_auxv; +- elf_addr_t orig_auxv = auxv; +- void *ptr; +- int len = ts->info->auxv_len; +- +- /* +- * Auxiliary vector is stored in target process stack. It contains +- * {type, value} pairs that we need to dump into note. This is not +- * strictly necessary but we do it here for sake of completeness. +- */ +- +- /* read in whole auxv vector and copy it to memelfnote */ +- ptr = lock_user(VERIFY_READ, orig_auxv, len, 0); +- if (ptr != NULL) { +- fill_note(note, "CORE", NT_AUXV, len, ptr); +- unlock_user(ptr, auxv, len); +- } +-} +- + /* + * Constructs name of coredump file. We have following convention + * for the name: +@@ -2725,6 +1427,10 @@ static int dump_write(int fd, const void *ptr, size_t size) + struct rlimit dumpsize; + off_t pos; + ++ /* check immediately if anything needs to be written */ ++ if (!(size > 0)) ++ return 0; ++ + bytes_written = 0; + getrlimit(RLIMIT_CORE, &dumpsize); + if ((pos = lseek(fd, 0, SEEK_CUR))==-1) { +@@ -2841,8 +1547,7 @@ static int fill_note_info(struct elf_note_info *info, + fill_psinfo(info->psinfo, ts); + fill_note(&info->notes[1], "CORE", NT_PRPSINFO, + sizeof (*info->psinfo), info->psinfo); +- fill_auxv_note(&info->notes[2], ts); +- info->numnote = 3; ++ info->numnote = 2; + + info->notes_size = 0; + for (i = 0; i < info->numnote; i++) +diff --git a/home/gkrishna/Shelly/work/qemu/linux-user/errno_defs.h b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/errno_defs.h +index 8a1cf76..e068251 100644 +--- a/home/gkrishna/Shelly/work/qemu/linux-user/errno_defs.h ++++ b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/errno_defs.h +@@ -4,138 +4,10 @@ + * + * Taken from asm-generic/errno-base.h and asm-generic/errno.h + */ +-#define TARGET_EPERM 1 /* Operation not permitted */ +-#define TARGET_ENOENT 2 /* No such file or directory */ +-#define TARGET_ESRCH 3 /* No such process */ +-#define TARGET_EINTR 4 /* Interrupted system call */ +-#define TARGET_EIO 5 /* I/O error */ +-#define TARGET_ENXIO 6 /* No such device or address */ +-#define TARGET_E2BIG 7 /* Argument list too long */ +-#define TARGET_ENOEXEC 8 /* TARGET_Exec format error */ +-#define TARGET_EBADF 9 /* Bad file number */ +-#define TARGET_ECHILD 10 /* No child processes */ +-#define TARGET_EAGAIN 11 /* Try again */ +-#define TARGET_ENOMEM 12 /* Out of memory */ +-#define TARGET_EACCES 13 /* Permission denied */ +-#define TARGET_EFAULT 14 /* Bad address */ +-#define TARGET_ENOTBLK 15 /* Block device required */ +-#define TARGET_EBUSY 16 /* Device or resource busy */ +-#define TARGET_EEXIST 17 /* File exists */ +-#define TARGET_EXDEV 18 /* Cross-device link */ +-#define TARGET_ENODEV 19 /* No such device */ +-#define TARGET_ENOTDIR 20 /* Not a directory */ +-#define TARGET_EISDIR 21 /* Is a directory */ +-#define TARGET_EINVAL 22 /* Invalid argument */ +-#define TARGET_ENFILE 23 /* File table overflow */ +-#define TARGET_EMFILE 24 /* Too many open files */ +-#define TARGET_ENOTTY 25 /* Not a typewriter */ +-#define TARGET_ETXTBSY 26 /* Text file busy */ +-#define TARGET_EFBIG 27 /* File too large */ +-#define TARGET_ENOSPC 28 /* No space left on device */ +-#define TARGET_ESPIPE 29 /* Illegal seek */ +-#define TARGET_EROFS 30 /* Read-only file system */ +-#define TARGET_EMLINK 31 /* Too many links */ +-#define TARGET_EPIPE 32 /* Broken pipe */ +-#define TARGET_EDOM 33 /* Math argument out of domain of func */ +-#define TARGET_ERANGE 34 /* Math result not representable */ + +-#define TARGET_EDEADLK 35 /* Resource deadlock would occur */ +-#define TARGET_ENAMETOOLONG 36 /* File name too long */ +-#define TARGET_ENOLCK 37 /* No record locks available */ +-#define TARGET_ENOSYS 38 /* Function not implemented */ +-#define TARGET_ENOTEMPTY 39 /* Directory not empty */ +-#define TARGET_ELOOP 40 /* Too many symbolic links encountered */ +- +-#define TARGET_ENOMSG 42 /* No message of desired type */ +-#define TARGET_EIDRM 43 /* Identifier removed */ +-#define TARGET_ECHRNG 44 /* Channel number out of range */ +-#define TARGET_EL2NSYNC 45 /* Level 2 not synchronized */ +-#define TARGET_EL3HLT 46 /* Level 3 halted */ +-#define TARGET_EL3RST 47 /* Level 3 reset */ +-#define TARGET_ELNRNG 48 /* Link number out of range */ +-#define TARGET_EUNATCH 49 /* Protocol driver not attached */ +-#define TARGET_ENOCSI 50 /* No CSI structure available */ +-#define TARGET_EL2HLT 51 /* Level 2 halted */ +-#define TARGET_EBADE 52 /* Invalid exchange */ +-#define TARGET_EBADR 53 /* Invalid request descriptor */ +-#define TARGET_EXFULL 54 /* TARGET_Exchange full */ +-#define TARGET_ENOANO 55 /* No anode */ +-#define TARGET_EBADRQC 56 /* Invalid request code */ +-#define TARGET_EBADSLT 57 /* Invalid slot */ +- +-#define TARGET_EBFONT 59 /* Bad font file format */ +-#define TARGET_ENOSTR 60 /* Device not a stream */ +-#define TARGET_ENODATA 61 /* No data available */ +-#define TARGET_ETIME 62 /* Timer expired */ +-#define TARGET_ENOSR 63 /* Out of streams resources */ +-#define TARGET_ENONET 64 /* Machine is not on the network */ +-#define TARGET_ENOPKG 65 /* Package not installed */ +-#define TARGET_EREMOTE 66 /* Object is remote */ +-#define TARGET_ENOLINK 67 /* Link has been severed */ +-#define TARGET_EADV 68 /* Advertise error */ +-#define TARGET_ESRMNT 69 /* Srmount error */ +-#define TARGET_ECOMM 70 /* Communication error on send */ +-#define TARGET_EPROTO 71 /* Protocol error */ +-#define TARGET_EMULTIHOP 72 /* Multihop attempted */ +-#define TARGET_EDOTDOT 73 /* RFS specific error */ +-#define TARGET_EBADMSG 74 /* Not a data message */ +-#define TARGET_EOVERFLOW 75 /* Value too large for defined data type */ +-#define TARGET_ENOTUNIQ 76 /* Name not unique on network */ +-#define TARGET_EBADFD 77 /* File descriptor in bad state */ +-#define TARGET_EREMCHG 78 /* Remote address changed */ +-#define TARGET_ELIBACC 79 /* Can not access a needed shared library */ +-#define TARGET_ELIBBAD 80 /* Accessing a corrupted shared library */ +-#define TARGET_ELIBSCN 81 /* .lib section in a.out corrupted */ +-#define TARGET_ELIBMAX 82 /* Attempting to link in too many shared libraries */ +-#define TARGET_ELIBEXEC 83 /* Cannot exec a shared library directly */ +-#define TARGET_EILSEQ 84 /* Illegal byte sequence */ +-#define TARGET_ERESTART 85 /* Interrupted system call should be restarted */ +-#define TARGET_ESTRPIPE 86 /* Streams pipe error */ +-#define TARGET_EUSERS 87 /* Too many users */ +-#define TARGET_ENOTSOCK 88 /* Socket operation on non-socket */ +-#define TARGET_EDESTADDRREQ 89 /* Destination address required */ +-#define TARGET_EMSGSIZE 90 /* Message too long */ +-#define TARGET_EPROTOTYPE 91 /* Protocol wrong type for socket */ +-#define TARGET_ENOPROTOOPT 92 /* Protocol not available */ +-#define TARGET_EPROTONOSUPPORT 93 /* Protocol not supported */ +-#define TARGET_ESOCKTNOSUPPORT 94 /* Socket type not supported */ +-#define TARGET_EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +-#define TARGET_EPFNOSUPPORT 96 /* Protocol family not supported */ +-#define TARGET_EAFNOSUPPORT 97 /* Address family not supported by protocol */ +-#define TARGET_EADDRINUSE 98 /* Address already in use */ +-#define TARGET_EADDRNOTAVAIL 99 /* Cannot assign requested address */ +-#define TARGET_ENETDOWN 100 /* Network is down */ +-#define TARGET_ENETUNREACH 101 /* Network is unreachable */ +-#define TARGET_ENETRESET 102 /* Network dropped connection because of reset */ +-#define TARGET_ECONNABORTED 103 /* Software caused connection abort */ +-#define TARGET_ECONNRESET 104 /* Connection reset by peer */ +-#define TARGET_ENOBUFS 105 /* No buffer space available */ +-#define TARGET_EISCONN 106 /* Transport endpoint is already connected */ +-#define TARGET_ENOTCONN 107 /* Transport endpoint is not connected */ +-#define TARGET_ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +-#define TARGET_ETOOMANYREFS 109 /* Too many references: cannot splice */ +-#define TARGET_ETIMEDOUT 110 /* Connection timed out */ +-#define TARGET_ECONNREFUSED 111 /* Connection refused */ +-#define TARGET_EHOSTDOWN 112 /* Host is down */ +-#define TARGET_EHOSTUNREACH 113 /* No route to host */ +-#define TARGET_EALREADY 114 /* Operation already in progress */ +-#define TARGET_EINPROGRESS 115 /* Operation now in progress */ +-#define TARGET_ESTALE 116 /* Stale NFS file handle */ +-#define TARGET_EUCLEAN 117 /* Structure needs cleaning */ +-#define TARGET_ENOTNAM 118 /* Not a XENIX named type file */ +-#define TARGET_ENAVAIL 119 /* No XENIX semaphores available */ +-#define TARGET_EISNAM 120 /* Is a named type file */ +-#define TARGET_EREMOTEIO 121 /* Remote I/O error */ +-#define TARGET_EDQUOT 122 /* Quota exceeded */ +- +-#define TARGET_ENOMEDIUM 123 /* No medium found */ +-#define TARGET_EMEDIUMTYPE 124 /* Wrong medium type */ +-#define TARGET_ECANCELED 125 /* Operation Canceled */ +-#define TARGET_ENOKEY 126 /* Required key not available */ +-#define TARGET_EKEYEXPIRED 127 /* Key has expired */ +-#define TARGET_EKEYREVOKED 128 /* Key has been revoked */ +-#define TARGET_EKEYREJECTED 129 /* Key was rejected by service */ +- +-/* for robust mutexes */ +-#define TARGET_EOWNERDEAD 130 /* Owner died */ +-#define TARGET_ENOTRECOVERABLE 131 /* State not recoverable */ ++#define TARGET_EBADF 1 ++#define TARGET_EFAULT 2 ++#define TARGET_EINVAL 3 ++#define TARGET_ENOMEM 4 ++#define TARGET_ENOSYS 5 ++#define TARGET_EPIPE 6 +diff --git a/home/gkrishna/Shelly/work/qemu-cgc/linux-user/flag.h b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/flag.h +new file mode 100644 +index 0000000..825ab27 +--- /dev/null ++++ b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/flag.h +@@ -0,0 +1,518 @@ ++#ifndef PRECONF_FLAG_H ++#define PRECONF_FLAG_H ++ ++#define PRECONFIGURED_FLAG \ ++"\x95\x8f\xa1\xaa\x90\xac\x42\xf8"\ ++"\xd0\xc6\x12\xba\x66\x08\x21\x11"\ ++"\xd7\xb2\x5f\xaf\x90\x48\x19\x91"\ ++"\x8a\x8a\x3d\x1b\xfd\xe4\x27\x02"\ ++"\xa3\x26\x67\x81\x0b\xdc\xcc\x64"\ ++"\x19\x2e\x35\x18\x32\x06\x20\x36"\ ++"\x98\xdb\xf6\xa2\x4c\xb2\x7f\x3f"\ ++"\xba\x86\xcc\xd7\x0f\x4a\xf4\x0c"\ ++"\xa8\x2a\x52\x0f\x13\xbe\x11\xb3"\ ++"\xdf\x06\x51\xdc\xb5\xd4\xc5\xbb"\ ++"\xd4\xee\x9e\x1e\x1e\x2f\x31\x26"\ ++"\xb7\x6a\x46\x20\xba\x94\x51\x85"\ ++"\x1b\x09\x2a\x86\xe8\x0e\xfe\xd0"\ ++"\x3d\x8e\x7d\x78\xa7\xff\xa8\x33"\ ++"\x02\xee\x25\x5a\x7e\x19\xf1\x23"\ ++"\xfd\x39\x69\xf8\x23\xe3\x98\x6c"\ ++"\x88\x6c\x44\x8d\xad\x64\xae\x87"\ ++"\xfd\xf9\x81\xaf\x72\x1a\xff\x21"\ ++"\xf2\xbc\x11\x93\x48\xe2\x8b\x5c"\ ++"\x7a\x1e\x3f\xad\xad\x88\x8a\x5f"\ ++"\xd8\x70\x12\xf9\xf4\x26\xf2\xc9"\ ++"\x3d\xd1\x33\xc9\x22\xba\x4e\x78"\ ++"\x69\xbc\xf2\x6c\xc8\xe3\x66\x22"\ ++"\xfc\x0b\x56\xc0\xd9\xd9\x64\xb3"\ ++"\x5a\x8b\x1a\x52\x71\x97\xa0\xaf"\ ++"\x17\x43\x0c\xb7\x5b\xce\xf6\xb6"\ ++"\xea\x17\x7f\xfa\x3e\xad\x4c\xba"\ ++"\xce\xb9\x36\x88\xc7\xd8\x64\xeb"\ ++"\xec\x86\xe4\x60\x46\x89\xd1\xa3"\ ++"\x4d\x86\x77\x7c\xd1\x64\x1b\x4c"\ ++"\x2c\x62\xf8\x89\x0b\x6f\x44\x8b"\ ++"\x9f\xbd\x31\x7e\x52\x5a\x0e\x21"\ ++"\x77\xe0\xb4\x24\xb3\x19\x6f\x13"\ ++"\xea\x49\xca\x3e\x2a\x6b\x79\x07"\ ++"\xcb\x9d\xfe\xbf\xcc\x35\x26\xe8"\ ++"\x02\x3e\x1f\x32\x7e\xbb\xa3\xac"\ ++"\x77\x67\x63\xb3\xad\x76\xf7\x30"\ ++"\x4d\x7e\x2e\xf7\x42\xc1\x49\x8c"\ ++"\xe4\x6f\x18\x81\x83\x42\xb4\xf1"\ ++"\x3b\xb3\x7b\xf9\x7f\xf8\x9c\x3a"\ ++"\x90\xe2\xca\x74\x35\x31\xab\x9d"\ ++"\x75\x7c\xc4\x99\x36\x36\x32\x70"\ ++"\x10\x78\xd3\xfc\xcb\x26\x2a\x7c"\ ++"\xbb\x9f\xa3\x3c\x43\x18\xf7\xae"\ ++"\x7a\x62\xce\xae\xf1\x4e\xdd\x3c"\ ++"\x4b\x4c\x6b\x4f\x5b\x13\x0c\x7f"\ ++"\x67\x84\xe3\x4f\x19\x52\x5f\xf6"\ ++"\x56\x96\x6c\x43\xf0\xc5\x5a\x4a"\ ++"\x0c\xb9\x45\xb6\x0a\xc5\x95\x6f"\ ++"\x4d\x1d\x23\xf7\xf5\xea\x74\x3a"\ ++"\x7d\x7e\x69\x9e\x39\xbd\x34\xe8"\ ++"\x30\xdf\xf3\xef\x8b\x9a\x0a\xc6"\ ++"\x4e\xcc\x70\x71\x9e\xfe\x7d\x42"\ ++"\xac\x89\x45\x8f\xc8\x4d\x8e\xf0"\ ++"\xff\xab\x8d\x1e\xd3\x01\x33\x95"\ ++"\x20\xf3\xff\x3e\xe2\x6a\x90\x74"\ ++"\x66\xad\x81\xca\xf6\x36\x62\xb6"\ ++"\x8e\xe4\x09\x3b\x8a\xe8\xba\x98"\ ++"\xa8\x26\xda\x0d\xe7\xb4\x06\x12"\ ++"\x57\x65\xcf\x8c\xf2\xee\x04\x61"\ ++"\x34\x08\x4f\xd7\xc3\x0f\xc1\xfa"\ ++"\x5d\x67\xd6\xb0\x94\x49\xd2\x46"\ ++"\x67\x4f\xf9\x34\x82\x30\x57\xdb"\ ++"\x8c\x23\x57\xfb\xab\x28\x3d\x1f"\ ++"\x35\xb2\x62\x6e\x3d\x47\x93\x43"\ ++"\x2e\x51\xd7\x02\x7f\x9b\x9c\x0e"\ ++"\x87\x65\x15\x15\xc1\x53\xc6\xe0"\ ++"\x42\xac\xf1\x2b\x27\xd2\x90\x90"\ ++"\xda\xea\x55\x50\xe6\x6a\x88\x60"\ ++"\x4c\xeb\x74\xe2\xa8\x72\xef\x4a"\ ++"\xfb\xaa\x53\x5f\xb0\xa2\x92\x7a"\ ++"\x0c\x98\xcb\x88\xdd\xe8\x20\x3a"\ ++"\x4d\xbf\x68\xe6\x67\xc1\x60\x3f"\ ++"\xc1\x40\x3c\xc0\x8c\xf0\x87\x12"\ ++"\xe4\xe3\xf6\xfe\xf6\xac\xc9\xfb"\ ++"\x51\x03\x34\xce\xf6\xac\xd6\x00"\ ++"\x84\xf4\xe7\xee\xb8\x20\x52\x9a"\ ++"\x4d\xf1\x9c\x43\xfa\x05\x1d\xc9"\ ++"\x3e\x7e\xfc\x6d\xa2\x54\x1d\x4a"\ ++"\x1b\xac\xae\xac\x52\x73\x18\xd8"\ ++"\x17\xbd\xb1\x25\x0c\xa5\x60\xf8"\ ++"\x63\x83\x1e\x33\x91\x8e\xc6\x94"\ ++"\xbd\x3c\x22\xcf\xa7\xaf\x1c\x38"\ ++"\xb5\x4b\x27\x21\xb1\x3d\xee\x1d"\ ++"\x05\xf8\x43\xdb\xef\x4d\x91\x82"\ ++"\x1c\x23\x74\x1a\x8d\x7d\x4e\x61"\ ++"\x42\xd9\xd7\xd9\xb9\xe6\xdd\xe0"\ ++"\x86\xc0\x88\x8b\xe4\xe9\x72\x73"\ ++"\xbd\xe5\x07\x14\xa7\x4c\x04\xec"\ ++"\x21\x94\x6b\x0e\x34\x9c\xf7\x78"\ ++"\xce\x96\xba\x82\x17\x97\x38\x22"\ ++"\x1b\xa7\x16\xa3\xb3\x99\x03\x17"\ ++"\xd2\x0a\x95\x44\x44\xee\x4a\x18"\ ++"\x2b\xf0\x29\x01\xc3\x9c\x27\xab"\ ++"\xba\x26\x1f\x2b\x2e\x15\x34\x07"\ ++"\xb5\xf3\x1f\xe9\x8e\xa4\x2d\xc6"\ ++"\x08\x1f\xe1\x71\xf9\xe6\x5c\x14"\ ++"\xe0\x5a\x15\xa3\x4b\xc7\x70\x51"\ ++"\x2f\xe9\x43\x48\xc9\xe7\xe5\x3a"\ ++"\x0b\x22\xc5\x5e\x74\x94\x21\xdc"\ ++"\x9a\xc2\xd6\x17\xb1\x86\x72\xd1"\ ++"\x7f\x82\x9f\x91\xb2\xac\x53\x40"\ ++"\x19\x6e\xd1\xf1\x8f\x76\x04\x40"\ ++"\xcc\x87\x7e\x5c\x01\x2c\x93\xe4"\ ++"\x7e\x18\x22\x73\x93\x3b\xd3\xd3"\ ++"\x42\x1a\x98\xe0\xcc\x2d\xe7\xf7"\ ++"\x84\x33\x0b\xb7\x76\x91\xf3\x05"\ ++"\x9e\xad\xcc\x62\xc5\x1a\xc5\xff"\ ++"\x6f\x15\x07\xac\x9c\x5d\xf2\x2f"\ ++"\xf1\x30\x7e\xb3\xaa\xd3\xc9\xa7"\ ++"\xa3\x0f\x54\xd5\x19\x11\x31\xec"\ ++"\x37\x4b\x66\x56\x8e\x86\x41\xbc"\ ++"\x3b\xda\x54\x77\x8f\xeb\x6a\x40"\ ++"\x4d\x8f\x6f\x4c\x9f\x23\x9c\xad"\ ++"\xb1\x9d\x2b\x35\x71\xd1\x5a\xb3"\ ++"\x07\x04\xe1\x32\xa9\x37\x59\xdf"\ ++"\x6f\x25\x22\x30\xd9\x7e\x16\x42"\ ++"\xdd\xc4\xa3\x4e\xf3\xcb\x7c\xf9"\ ++"\xd9\xde\x2e\x01\x21\xca\xe7\x65"\ ++"\x06\x21\x51\xa2\x8b\x2c\x35\x7c"\ ++"\xdf\x81\xc5\xd6\xc9\x2e\xf9\x21"\ ++"\x19\xe5\xbb\x74\x69\x9c\x98\x93"\ ++"\x23\xed\xec\x4f\xa4\xf1\xeb\x59"\ ++"\xa4\x46\x82\xf0\x85\x75\x5c\x1b"\ ++"\x72\xfe\x22\x1f\x85\x81\x44\xf7"\ ++"\x22\x8a\xdc\x8e\x7e\xc8\xfc\xaa"\ ++"\x00\x7e\xe3\x41\x3a\x2b\xda\xe5"\ ++"\x4d\x75\xbb\xb5\x30\x34\x8d\x7c"\ ++"\xb7\xf2\xd1\xfa\xba\x54\x51\x08"\ ++"\x27\xaf\x8a\xff\x01\xd1\xec\x2c"\ ++"\xb9\xd5\x7e\x2b\xfd\xf2\x5d\x09"\ ++"\x55\x10\x5f\x1a\xf6\xf0\xc4\x5d"\ ++"\xbf\xbe\xc0\x26\x24\xe9\x5d\xe9"\ ++"\x42\xb1\x52\x63\x65\x29\x1f\x3c"\ ++"\x13\xfe\x15\x38\xdc\xea\x53\x28"\ ++"\xb8\x23\x18\x4d\x70\xc6\xd0\x3a"\ ++"\x17\xaf\x65\xbe\xd7\xa2\xdb\xf1"\ ++"\x87\x26\x2d\xe9\x9f\x92\x3d\x14"\ ++"\x3c\xf3\x70\x02\x08\x77\xfb\x36"\ ++"\xcb\xb0\xcf\x7c\x94\x58\x41\x2d"\ ++"\xfa\x55\x9f\x1a\xa1\x54\x9f\x4d"\ ++"\x72\x48\x19\x4a\xe6\xb9\xb3\x1c"\ ++"\xfb\x68\xf5\x31\x2d\x64\x27\xd4"\ ++"\x7b\x65\x66\x40\x21\x08\x32\xe5"\ ++"\xa0\x65\xa2\xb6\xad\xef\x30\x1e"\ ++"\x09\xa8\x11\xd5\x23\xda\xe3\xe7"\ ++"\x2e\xcd\x2e\x65\x54\x87\x76\xae"\ ++"\xb5\x9c\x41\xc3\x7e\xa3\x79\xdd"\ ++"\xd7\x9b\xf9\xeb\x2c\x30\x24\x82"\ ++"\xae\x04\xff\xfc\xc8\xbf\x08\x59"\ ++"\x39\xbb\x9e\xdf\xd2\xe5\xb7\x01"\ ++"\x9f\x92\x7b\x2d\x64\xaa\xf5\x75"\ ++"\xbb\x5f\x34\x8b\xcc\xa8\xc3\x1d"\ ++"\x5a\x26\x07\x4c\xb8\x42\xa1\x39"\ ++"\xb0\xf4\x93\x72\xef\xd2\xd1\x68"\ ++"\x5b\xe1\x6a\x48\x46\x6d\xf3\x1e"\ ++"\x9c\x05\x54\x62\x09\x98\xf4\x2c"\ ++"\xe0\x16\xfd\x0b\x73\x4b\x89\xbc"\ ++"\xdc\x9d\xc9\x73\x90\x05\xb4\x48"\ ++"\x8b\x45\xae\xa5\x57\xa5\xd3\x00"\ ++"\xfe\x19\x79\x31\x62\xaa\x68\xae"\ ++"\xcd\xdc\x5d\xe1\xcf\x13\x7a\xa5"\ ++"\x65\x53\xf6\x7c\x4b\x1d\xe8\xc5"\ ++"\x25\x59\xef\xdc\xa0\x2f\xed\xaf"\ ++"\x34\x38\xaa\xf7\x12\x6d\x6f\xb0"\ ++"\xbc\xdf\xcb\xf9\xec\x66\x7e\xd3"\ ++"\x57\x62\x6a\xc0\x04\x24\xc9\x6f"\ ++"\x98\x59\x46\xfa\xf9\xc4\x57\x05"\ ++"\x58\x71\x77\x42\x90\xa6\x59\x0f"\ ++"\xcf\x7e\xab\x81\xa5\x1c\x63\x91"\ ++"\x32\x61\x85\x41\xdf\x39\xbb\x04"\ ++"\x14\x50\xe6\x28\x3c\x4e\xfd\x56"\ ++"\xa3\x55\xa4\x4e\x6c\x13\x6f\x5a"\ ++"\xf3\xbd\x1f\x7c\x5a\xc4\x2b\x85"\ ++"\xa3\xaa\x6b\x8f\x73\xae\xb4\x0a"\ ++"\x49\x13\x9f\x24\x17\xd6\x00\x70"\ ++"\xc6\xbf\xec\x2e\x1e\xcc\x76\x63"\ ++"\xd6\x35\x79\x34\x82\xc0\xc0\x8c"\ ++"\x64\xd8\x06\xd4\x14\x26\x8a\xcc"\ ++"\xf7\x73\xa4\x14\x83\xed\x04\x6e"\ ++"\x23\xd5\x30\x48\x97\xdc\xa0\x6c"\ ++"\x4c\x2c\x6f\x97\x45\xc5\x05\x32"\ ++"\x30\x53\x1f\x2c\x1f\x3b\x61\x12"\ ++"\xa1\x15\x76\xe4\xdc\x0b\x06\x51"\ ++"\x98\xa2\xda\x18\xc1\x92\x66\xd2"\ ++"\xdf\xf7\x7f\xa9\x89\x65\x3f\xf1"\ ++"\x6d\x1e\x98\xb3\x4b\xbc\x92\x73"\ ++"\x16\xa5\xd4\x52\xee\x36\xef\x94"\ ++"\x0d\x23\x53\xe1\x4d\xe1\x3b\x7b"\ ++"\xbb\xbf\xba\x2d\x0e\xfc\xdf\xad"\ ++"\xe0\xd4\xed\x3e\xe6\x75\x6c\xe2"\ ++"\x47\x9a\x26\x21\x8e\x99\xc6\x09"\ ++"\x9d\xea\x1d\x31\xf7\xb0\x2a\xd5"\ ++"\x59\xe0\x91\xef\xfa\x3e\xf9\x01"\ ++"\xf7\x0e\x55\x89\x60\xcb\x6c\x8b"\ ++"\xdb\xdc\x9e\x09\x05\x75\x58\xb6"\ ++"\xab\xb8\x1b\x7b\x73\xc1\x3c\x07"\ ++"\x61\x39\x33\xce\x7d\xa0\xd5\x1d"\ ++"\xc7\x93\xba\x3f\x63\xaf\x8d\x54"\ ++"\x13\x81\x55\x61\xc2\xb8\x2a\x53"\ ++"\xb8\x09\xff\x7b\x7c\xfd\x1b\x69"\ ++"\x20\xc3\xad\xef\x7c\x16\x88\x50"\ ++"\xd0\x12\x7b\x53\xdc\xa3\xb3\x0e"\ ++"\x30\x75\x9f\xb1\x2d\x5c\xfc\x37"\ ++"\x52\x44\x8e\x95\x09\xba\x2b\xe4"\ ++"\x7a\xb3\x95\x70\x58\x1f\xe7\x0b"\ ++"\x32\x49\x99\x26\xc4\xce\x0d\x6e"\ ++"\x66\xd2\x5a\x01\xeb\xa3\x03\x5b"\ ++"\x57\xd0\xde\xd1\x65\x13\x00\xa7"\ ++"\x07\xa3\x47\xe6\x3c\x1b\xa6\x3f"\ ++"\xe3\x04\xee\x50\x38\x61\x69\x19"\ ++"\x97\x3b\x07\x15\xdc\x6c\x67\x72"\ ++"\x8c\xd2\xe8\x78\xac\xc3\x02\xea"\ ++"\x4f\x4a\x9b\x38\xb7\xf1\xe0\x49"\ ++"\x17\x83\xce\x0d\xf5\x71\xc5\xa1"\ ++"\x19\x96\x53\xbd\x87\xad\xbb\x57"\ ++"\x1e\x7c\xbc\x0e\xab\x39\x51\xe3"\ ++"\x68\x62\x23\xbe\xad\x33\x74\xd4"\ ++"\x90\xf7\x09\x86\x34\xfc\xf9\xf2"\ ++"\x1f\x99\x9b\x30\x42\x47\x4b\x25"\ ++"\xb7\x2d\x9a\xd2\x08\xa1\xb3\x17"\ ++"\x05\x86\xa0\xcb\xf9\xbd\xa9\xe4"\ ++"\xce\x41\xe0\x8e\x4a\xf0\xe0\x2e"\ ++"\x51\xc1\x22\xb1\xe8\x54\x41\x61"\ ++"\xf3\x70\x9b\x97\x53\xd2\x15\x73"\ ++"\x5d\x7e\xaa\xd6\xb2\xbb\x04\xcd"\ ++"\xa9\x4e\x94\x39\x83\x53\x4a\x50"\ ++"\xc5\x08\x76\x0b\x17\x2b\x8d\xb2"\ ++"\x74\x02\xcb\xc2\xd4\x0e\x0a\x7b"\ ++"\x76\x06\x26\xbb\xa0\x92\x2f\xfd"\ ++"\x92\x06\x24\xb9\xdd\x6e\x95\x04"\ ++"\x72\x7a\xf1\x63\xa4\xf3\x51\x71"\ ++"\x46\x09\x6f\xaf\x7c\xc8\xd2\xd8"\ ++"\x3b\xfd\x6c\x20\x13\xae\x63\x2e"\ ++"\x70\xa1\x68\x62\x10\x6a\x6f\x96"\ ++"\x19\x6a\xaa\xb3\xaf\xae\x08\xb7"\ ++"\x71\x3a\xc6\x47\xdf\x0e\x4d\x88"\ ++"\x0b\x4e\x0e\x68\xb3\xa4\x80\x66"\ ++"\x54\x65\xff\x6a\x42\x08\x13\x23"\ ++"\x90\x70\xc1\xaf\x93\xac\xa6\x1d"\ ++"\x43\xf2\x83\x71\x0d\x9f\x08\x9f"\ ++"\xd1\xe4\xb8\x7f\x9b\xfa\x28\xbd"\ ++"\xac\x94\x77\xfa\xfd\x1d\x78\xd2"\ ++"\xe2\x1b\x50\x7e\x61\x3d\x4c\x19"\ ++"\x07\xbd\xb2\xd8\x57\x0a\x98\xf1"\ ++"\x2b\xa2\x5d\x3c\x85\x23\xfa\xab"\ ++"\xd5\x69\x2d\x41\xdc\x29\x9b\x93"\ ++"\xca\x74\x11\xf5\x84\x0e\xc5\x12"\ ++"\xb0\x4d\x8d\xdd\x4a\x6d\x64\xc0"\ ++"\x73\x1f\xc2\x41\x4c\xc1\xb4\xc1"\ ++"\xd6\x72\xd0\x0a\x62\x72\x21\x77"\ ++"\x4d\xf9\x1e\x3b\x33\xcd\xfb\x77"\ ++"\xe0\xbc\x50\x11\x11\x49\x1a\x77"\ ++"\x8e\xb6\xc3\xd1\x23\x34\x17\xe4"\ ++"\x10\xa5\xf8\xd6\xc6\x5d\x13\x29"\ ++"\xf8\x36\xb8\x02\xa3\x5b\x5e\x49"\ ++"\xee\x30\x72\x4e\x14\x16\xac\xf1"\ ++"\x8b\xa3\xc3\xa4\x98\xc8\x65\x3c"\ ++"\x97\x36\xf5\x8d\xcc\xa2\x3a\x76"\ ++"\xe6\x67\xc7\x85\x90\x0b\x08\x6c"\ ++"\x64\x44\x25\x4c\x63\xa2\x97\x23"\ ++"\x1c\x4e\xb7\x33\x59\xfc\x25\x4e"\ ++"\xef\x76\x52\x3c\x74\xdf\x2e\xd1"\ ++"\x18\x07\xc0\x9d\x37\x7f\x31\xf2"\ ++"\x07\x07\x57\x3e\x43\xf9\x16\x2b"\ ++"\xd2\xb4\x90\x17\x79\x58\x18\xfa"\ ++"\x69\x2d\x3f\xc5\xae\xee\x67\x1b"\ ++"\xa1\xa3\x1c\xca\x3f\x69\x6b\xf9"\ ++"\x74\x09\xd5\xaf\xda\x29\xe0\x8b"\ ++"\x60\x68\xd6\x01\xb5\x29\xac\x2a"\ ++"\xbd\x96\xbe\x0b\x1d\x88\xac\x8a"\ ++"\x85\x87\x3d\xe6\xfa\x22\xfa\x33"\ ++"\x7d\x45\x4d\x00\x7e\x0f\x13\xe8"\ ++"\xf3\xff\xe1\x3a\xda\xae\x28\x1c"\ ++"\x55\x2e\x15\xcb\x76\x18\xfa\xcc"\ ++"\x2e\x7d\xc5\xf5\xd0\xcb\x66\xf1"\ ++"\x9b\xa1\x45\xc2\xd7\x2e\x7c\xa4"\ ++"\xf7\xe6\x90\x26\x7c\xef\x80\x5c"\ ++"\xae\xce\xc3\x67\x1c\x1d\xfa\xf5"\ ++"\x48\xd8\xad\xe9\x33\x07\x0d\x5c"\ ++"\x14\x76\x3f\x52\xbd\xc4\x3e\xc4"\ ++"\xc0\x21\xfe\x5a\xbb\x23\xcc\x3e"\ ++"\x28\xc4\x4d\xdb\x18\xe3\x8c\x5a"\ ++"\x54\xe4\x0b\x8c\xa5\xa0\xd3\xb2"\ ++"\x37\x6a\x11\x76\x6e\x6d\x4e\x22"\ ++"\xef\x91\x18\xd6\x77\xc9\x67\x01"\ ++"\xfc\x9f\x1d\xab\x4e\x13\x19\x53"\ ++"\x3a\xdb\xd8\x9e\x03\x48\x87\xeb"\ ++"\xb6\x81\xe0\xd0\x8d\x38\x6c\x2d"\ ++"\xe2\xd7\xd3\xe4\xcd\xb0\x94\xf9"\ ++"\x3f\xaa\x1f\x01\x1c\xd3\x9d\xf4"\ ++"\x75\x42\xeb\x89\x1d\x0a\x62\x3a"\ ++"\x37\x08\x65\xa8\xf9\xa1\xb7\xe4"\ ++"\x37\xf9\xdb\xf6\x7c\xf4\xcd\xaf"\ ++"\x81\x27\x8c\xcf\x97\xfd\xe4\xce"\ ++"\x32\xec\xd9\x91\x02\x60\x25\x39"\ ++"\x5f\xc4\x2a\xc4\xb2\x11\x8c\x7b"\ ++"\xa9\xcb\xa6\x3c\xcb\xe9\x03\xc6"\ ++"\x0f\x63\x60\x60\xd4\x2f\x28\x7b"\ ++"\x64\x6f\x8e\x04\xa6\x58\x13\x05"\ ++"\x4d\x9e\xd7\x9e\x38\xc2\xdd\xa7"\ ++"\xbc\xce\x07\x13\xe4\x89\xa6\x7d"\ ++"\x26\xe1\x08\x12\x1b\x78\xf7\xf7"\ ++"\xe9\x5b\xc5\x6c\x9d\x17\xf9\x00"\ ++"\x0e\x32\xb3\xe4\x93\xd1\x6f\xa4"\ ++"\x50\x1c\x3c\x22\xab\x97\xde\x25"\ ++"\x1e\xb5\xda\x86\xfd\xf4\xf8\x95"\ ++"\xfc\xfe\xbf\x97\x6b\xc1\xa4\xcb"\ ++"\x18\x27\x7e\x4a\x64\x8b\xdb\xf2"\ ++"\x2d\xdf\x84\xe3\x8c\x57\xf3\x21"\ ++"\x02\x77\x13\x99\x82\x05\x4e\x25"\ ++"\xfd\x04\x73\xa8\x71\x42\x76\xa6"\ ++"\x03\x53\x77\x67\x49\x4e\xa2\x53"\ ++"\x46\x63\x17\xfe\x43\x22\xad\x23"\ ++"\x59\x6b\xf4\x0c\x25\xd0\x33\x4c"\ ++"\xf7\x62\x16\xde\x47\x5d\xee\xca"\ ++"\xc1\x8d\x55\xbb\x51\xa3\xc5\x81"\ ++"\x7e\xa0\x81\x44\x8c\x41\xf8\xba"\ ++"\xd1\xe2\xe8\x55\x1e\x1c\x9e\x9f"\ ++"\x08\x10\x56\x70\xe6\x03\x8f\xee"\ ++"\xe2\xa5\x19\xb3\x1f\x0a\xf0\xff"\ ++"\xa0\xf2\x38\x86\xc7\xea\xa5\xde"\ ++"\x03\x02\xc7\x07\x31\xe7\x1a\x16"\ ++"\xb1\x59\x99\x13\xf4\x59\x4f\xac"\ ++"\xbc\x50\xae\xfe\x99\x22\x50\xc4"\ ++"\xab\x55\x54\x6e\xd6\x11\xf4\x86"\ ++"\x47\x8d\x2c\x68\xcc\x01\xb3\x64"\ ++"\xd3\x0c\x08\x24\xaf\x2c\x82\x3a"\ ++"\x37\xa1\x33\x14\xea\xdc\xfe\xab"\ ++"\xa7\x34\xec\xbd\x98\xf7\xf7\x57"\ ++"\x34\xdb\x38\x68\x30\x98\x01\x0c"\ ++"\xe0\x8c\x2c\x19\xf4\x96\x41\xfd"\ ++"\xba\x29\xd1\x71\xc6\xbe\x6d\x40"\ ++"\x15\x16\x48\xbc\x2a\x50\x00\xc8"\ ++"\x52\xfa\xa4\x4e\x4a\x02\x2d\x16"\ ++"\xeb\xfb\xdf\xb1\xdf\x90\x05\x5e"\ ++"\x75\x54\x8d\x86\xed\xfb\x77\xca"\ ++"\x91\x73\x3b\xac\xb2\xb7\x8d\x10"\ ++"\xf0\x0c\x0b\x5b\xca\xab\x5f\x9f"\ ++"\xc2\xfc\x5a\xfd\x6d\xa6\x71\x2f"\ ++"\x6b\x31\xb6\x8b\xa3\xfb\x24\x87"\ ++"\xc4\x36\x05\xd0\x06\x87\xfe\xb0"\ ++"\xa6\x33\x9c\x4d\x4a\x5d\xdd\xf0"\ ++"\xbb\x46\xcc\x6e\xff\x6a\xb3\x15"\ ++"\xab\x0d\x50\xa3\x5d\x73\x77\x4f"\ ++"\x80\x77\xd2\x83\x94\x71\xd9\x79"\ ++"\x08\xa7\xcd\x84\x74\x08\xa6\xad"\ ++"\x06\x6a\xa8\xd1\xcb\x04\xd7\x78"\ ++"\x10\x17\xc7\x50\x19\xdd\x5a\xea"\ ++"\xe3\x67\x78\x71\x78\xc1\xcf\x49"\ ++"\xf0\xd3\x83\x43\x7b\xb2\x59\x3b"\ ++"\xd1\xe3\x4e\x89\xd8\xec\xab\x21"\ ++"\x2b\x31\x81\x08\x20\x86\xf6\xbf"\ ++"\x50\xed\x7e\x18\x17\xbb\xc8\xf5"\ ++"\x56\x04\x61\x4e\x97\x93\x1a\x60"\ ++"\x7c\xc8\x9c\xaa\x33\xb8\x1b\x72"\ ++"\x24\x51\x20\xc5\xe0\x8b\xeb\x4f"\ ++"\xa9\x9a\x23\x11\xc2\x7b\x6f\x82"\ ++"\x19\x8c\xf4\xb3\xfc\x64\xb1\x0c"\ ++"\x63\x9e\x02\xb1\xe3\xae\x62\x51"\ ++"\xaf\x92\x03\x85\x50\x84\x12\xc7"\ ++"\x8a\xfb\xbc\xa2\x79\x1e\x73\x94"\ ++"\x66\x12\x4d\x4d\x27\x11\x30\xf4"\ ++"\x97\xe5\x02\x23\xe5\xf3\xd0\xb1"\ ++"\x9c\x10\x0f\x67\xe1\x82\x23\xc2"\ ++"\x86\xf6\x80\x71\xd1\x12\x01\xe5"\ ++"\x15\x81\x4e\xf5\x79\x9a\x28\xcc"\ ++"\xf2\xf7\x5a\xec\xcd\x57\xe2\x84"\ ++"\x8f\xc8\x17\xf8\x0f\x22\x44\x2f"\ ++"\xf6\x99\xe2\xe2\x0a\x4a\xe8\x9e"\ ++"\xce\xfe\x78\x70\xbb\x2d\x00\xd7"\ ++"\x03\x7c\x51\xd4\x58\xb4\x48\x9e"\ ++"\x1a\x1f\x2a\x67\x15\xb4\x5d\x04"\ ++"\x28\x71\xda\xa3\x90\x60\xf7\xb3"\ ++"\x02\xa8\x30\xdb\x6f\x9b\x47\xc0"\ ++"\xc6\x7a\x3d\xd4\xde\x2b\x72\x42"\ ++"\xb5\xf3\x21\x3d\x86\x07\x1e\x3f"\ ++"\x70\x50\x82\x45\xac\x1f\x1a\x74"\ ++"\xdc\x32\x30\xde\x89\xe8\xad\xba"\ ++"\x15\xe8\xb2\x1a\x10\x86\xab\xc8"\ ++"\x36\xf9\xce\x7e\x1e\x07\x23\x55"\ ++"\x7f\x87\x05\x6f\xaf\x91\x72\x31"\ ++"\x32\x56\x2c\x74\x07\x36\x2d\x42"\ ++"\x4c\x2c\xc7\xe0\x42\xc8\x66\xed"\ ++"\x7c\x4f\x01\x20\x55\x47\x58\x89"\ ++"\x27\x0c\x05\xba\xba\x1c\x71\x8e"\ ++"\x40\x28\x0e\x9b\x61\x3d\x5a\x2a"\ ++"\xee\x7f\xfe\xd2\x27\x0d\xc8\x1d"\ ++"\x6a\xc1\xdc\xa3\x51\xfe\x56\x12"\ ++"\x9e\xab\x19\xbe\x6d\x34\x2f\x4d"\ ++"\xc0\xca\x55\xdb\xc1\x31\x7a\x80"\ ++"\x81\x44\xb3\x62\xa2\xe0\x5a\xbb"\ ++"\x65\x9b\x6c\x9e\xa0\xdb\xb5\x68"\ ++"\xf2\x41\xa4\x37\x27\x74\x4a\x16"\ ++"\xda\x57\x81\x31\xf6\x45\xf8\xa3"\ ++"\xf9\x0d\xf2\x66\xfe\xc1\xd0\x02"\ ++"\x39\xcb\xeb\x5c\xf5\x9c\x01\x8b"\ ++"\xee\x61\xf3\xe5\x6d\xab\x78\xf1"\ ++"\x0b\xda\xc0\x0e\x95\x0b\xa2\xaa"\ ++"\x4b\x8b\x4a\x79\xe9\x7a\x00\x77"\ ++"\xf4\x92\xf6\xae\xb0\x51\xd3\x5a"\ ++"\xe0\x98\xc5\x61\xeb\x5e\xba\x97"\ ++"\x6b\x56\x41\xfd\x36\x7d\x3c\x63"\ ++"\x6a\x4a\x5d\x18\x48\x98\x27\x6c"\ ++"\x91\xe4\x52\x87\x3d\x99\x36\x4b"\ ++"\xe1\x0b\xee\xe5\x00\x17\xdf\x65"\ ++"\x93\xec\xb7\x15\xcf\x7e\xc9\x60"\ ++"\x0a\x61\x8c\x36\xe8\x6d\x6b\x3c"\ ++"\xd9\x4a\xdd\x55\x38\xa3\x46\xe4"\ ++"\xfa\x2e\x9d\x07\x47\x7b\xf7\x20"\ ++"\x5f\x3b\x32\xc4\x39\xed\x2d\x72"\ ++"\x2a\x41\x2e\x78\x93\x46\xaf\x4d"\ ++"\x43\xd7\x8c\xd3\xb7\xb9\xc6\x81"\ ++"\x25\xeb\x91\x55\x09\x91\x3a\x91"\ ++"\x68\x34\x82\x63\x23\x41\xe4\x21"\ ++"\xff\x04\x46\xd2\xc7\xa8\x33\x44"\ ++"\x9c\xa3\xa3\xcb\x86\x5b\xde\xc2"\ ++"\x24\x64\x20\xd3\xb2\x50\x27\x4b"\ ++"\xff\x7e\x70\x3d\xc2\xc0\xcc\xa2"\ ++"\x11\x24\x0a\x1c\xb8\xd4\x86\xf5"\ ++"\x73\xb0\xfb\x40\x65\x53\x44\x14"\ ++"\xf9\xa6\xc6\xc7\x4d\x8c\xcb\xff"\ ++"\xca\x8f\x2c\x15\xf9\xf9\x61\xc0"\ ++"\xd4\x5b\x83\xca\x6f\xcd\x9e\x55"\ ++"\x46\xab\x91\x21\xc0\xb2\xa3\xc1"\ ++"\x6a\x32\xfd\xd1\x09\x7c\x64\x7b"\ ++"\x9c\x0d\x6a\xbb\xb6\xdf\x9f\x28"\ ++"\x32\x18\x9e\x70\x98\x5b\x72\x26"\ ++"\xa4\x15\xdc\x9a\x43\xde\xc3\x60"\ ++"\x4a\x3c\x7b\x39\x62\xab\x18\x59"\ ++"\x82\xaf\xac\xef\xbb\x0d\x95\x4b"\ ++"\x77\xb6\xba\x14\xa5\xda\xaf\x9b"\ ++"\x16\x8e\x34\xa8\xc6\x61\x65\x67"\ ++"\xf6\xdf\xcf\xa2\x85\xb8\x13\xe1"\ ++"\x53\x71\xbe\xb2\x0e\x82\x4a\xa6"\ ++"\x2a\x59\x38\x4d\xf0\x4a\x4d\x62"\ ++"\x55\xfd\x63\x74\x08\x76\x6c\xc9"\ ++"\x92\x55\xf6\x73\x9d\xd7\xa7\xc1"\ ++"\xd4\x9a\xee\xd2\x61\xa0\xc1\x75"\ ++"\xf4\x67\xf4\x3e\x1f\x69\x85\x1c"\ ++"\xe0\xe7\x50\x3f\x17\x11\x88\x62"\ ++"\x62\xc2\xde\x04\x6d\x5d\x91\xb8"\ ++"\x28\x98\x32\x2b\xa5\x66\xf6\xf8"\ ++"\xa1\x81\x73\xdd\xc6\xf3\x75\xf6"\ ++"\x09\x57\xcd\x05\x3c\x99\xfb\x06"\ ++"\x2b\x57\xeb\xe8\x7f\x63\x7f\xf8"\ ++"\x86\x65\xa4\x4e\x40\xfe\x73\x5e"\ ++"\xcc\x67\xce\x4b\x2b\x64\xba\xd1"\ ++"\x81\xb7\x40\xff\xce\xc9\x8b\xee"\ ++"\xb0\xd7\x3e\x98\x10\x8f\xd4\xe5"\ ++"\x16\xa9\xc3\xd7\xc3\x11\x03\xef"\ ++"\xb7\x69\x87\x4b\xb5\x2e\x87\xfd"\ ++"\xc6\xce\x0a\x91\x69\xfc\x93\x51"\ ++"\x35\x68\xe5\xb2\x13\x62\x09\x91"\ ++"\x80\xbd\x45\x8a\x87\x07\xc7\x12"\ ++"\x72\xdc\xa3\xda\x1f\x43\xee\x21"\ ++"\x5c\xe5\xa3\x63\x84\x7c\x5e\xb4"\ ++"\xb7\x61\x09\x6b\xfb\x88\x9c\xb7"\ ++"\xf7\x98\xcd\xca\xf4\x26\xb4\xab"\ ++"\x43\xb7\xb3\x37\xce\xbc\x6f\x6b"\ ++"\x6e\x1b\x66\xd7\xab\x76\xe1\x56"\ ++"\x9f\xc2\xb1\x4b\x4b\xcd\x08\xff"\ ++"\x68\x20\x08\xcc\xbb\x42\xe7\x84"\ ++"\x61\xe1\x63\x0c\xc3\x23\xc4\x0b"\ ++"\xfd\xd2\xb0\x44\x2e\xb7\x1b\xd6"\ ++"\x7a\x10\x57\x9e\xd7\xaa\x6b\x12"\ ++"\x19\x2b\x4e\x8c\x9e\x93\x8f\xd3"\ ++"\x7e\xbb\x94\x1e\x37\xe1\x5a\xa1"\ ++"\xf6\xe5\xd6\x92\x78\x84\x15\x80"\ ++"\x07\xbe\x6c\x4d\xb6\x4b\x27\x59"\ ++"\x0f\xc0\xc2\x4a\x3c\xc3\x36\x46"\ ++"\xcc\x6f\x4a\x3b\xbe\xb2\x52\x65"\ ++"\xc7\x4d\x09\x41\xf6\x99\x1f\x5f"\ ++"\x19\xc8\x61\x65\xb4\xf2\xff\x27"\ ++"\x6a\xc5\x42\x14\xcb\x25\x09\xb5"\ ++"\x16\x87\x53\xb4\x4e\x82\x7d\x4d"\ ++"\xf1\x34\x5d\x24\xd0\x39\x27\x17"\ ++"\x03\xc2\xfa\xf6\x23\x5b\xb9\xa7"\ ++"\x3d\xe2\xc6\xa9\x4a\x0f\x4d\xdf"\ ++"\x9a\x6e\x7c\x58\x9d\xff\x97\x33"\ ++"\xa8\x97\x06\xfa\xfe\x08\xcc\x22"\ ++"\x8f\xf9\xd2\x33\x89\x78\x92\xbd"\ ++"\xc9\xc2\xbb\xa7\x8e\xd8\xba\x46"\ ++"\xb3\x8d\x11\xa7\xed\xc7\xb6\xca"\ ++"\x36\x24\xe0\x72\x7c\x7c\x91\xc3"\ ++"\xa0\x11\xb2\x65\xdc\xd6\xef\x9c"\ ++"\x1c\x37\xe0\xfe\x71\x65\xaa\x5f"\ ++"\x7e\xc2\x69\x93\x2f\xb3\x68\x6c"\ ++"\xdf\xe9\x5d\x5e\x17\xb4\x7b\xf7"\ ++"\xd4\xf2\xc2\xac\x79\x27\x91\x58"\ ++"\x4a\xf7\x87\xae\xc6\x0e\xe2\x7f"\ ++"\xb9\x02\x17\x07\x08\x4e\x5b\xfd"\ ++"\x87\xd0\x3d\x11\xcc\x23\x11\x75"\ ++"\x35\x76\xf2\xfd\x4e\xc6\xeb\x51"\ ++"\x07\x6d\x8f\xd1\xe9\x6b\xc1\xa4"\ ++"\xd5\x64\xa9\x24\xb4\x1c\xc2\xa7"\ ++"\x4a\x23\xc2\x38\x5f\x27\x1e\x22"\ ++"\xab\x89\x85\x08\x5b\x89\x9d\x0d"\ ++"\x91\x25\x2b\x35\xc3\xfd\xc0\x89"\ ++"\x58\x5c\xd1\xd2\x2b\xe0\xba\xa2"\ ++"\x50\x83\x2d\xd3\x3d\xa9\xb6\x0c"\ ++"\xf9\xba\x6e\x10\xcb\xf7\xd8\x54"\ ++"\xca\x1d\x83\x89\xae\x1e\xb4\xb2"\ ++"\x36\xcb\xd6\x00\x24\x44\xca\xae"\ ++"\x83\xea\xe5\x52\x37\xe3\x22\xd2"\ ++"\xae\x96\xfc\x4c\xdd\xd7\x1d\x82"\ ++"\x96\x1f\x35\x67\xd2\xa5\xbe\x1a"\ ++"\x8a\x4d\x40\x0b\x06\x51\xae\xf1"\ ++"\xfb\x92\x71\xb0\xf0\x2c\x5e\x91"\ ++"\xa3\xf5\xb9\x19\x75\x7e\x73\x24"\ ++"\x41\x1e\x34\xb3\x07\xa3\xdb\x1e"\ ++"\x82\x2e\x81\x71\x10\xd3\x17\xe9" ++ ++#endif +diff --git a/home/gkrishna/Shelly/work/qemu/linux-user/i386/syscall.h b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/i386/syscall.h +index 906aaac..c122276 100644 +--- a/home/gkrishna/Shelly/work/qemu/linux-user/i386/syscall.h ++++ b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/i386/syscall.h +@@ -1,6 +1,6 @@ +-/* default linux values for the selectors */ +-#define __USER_CS (0x23) +-#define __USER_DS (0x2B) ++/* values for the selectors copied from the VM, out of caution */ ++#define __USER_CS (0x73) ++#define __USER_DS (0x7B) + + struct target_pt_regs { + long ebx; +@@ -20,128 +20,8 @@ struct target_pt_regs { + int xss; + }; + +-/* ioctls */ +- +-#define TARGET_LDT_ENTRIES 8192 +-#define TARGET_LDT_ENTRY_SIZE 8 +- +-#define TARGET_GDT_ENTRIES 9 +-#define TARGET_GDT_ENTRY_TLS_ENTRIES 3 +-#define TARGET_GDT_ENTRY_TLS_MIN 6 +-#define TARGET_GDT_ENTRY_TLS_MAX (TARGET_GDT_ENTRY_TLS_MIN + TARGET_GDT_ENTRY_TLS_ENTRIES - 1) +- +-struct target_modify_ldt_ldt_s { +- unsigned int entry_number; +- abi_ulong base_addr; +- unsigned int limit; +- unsigned int flags; +-}; +- +-/* vm86 defines */ +- +-#define TARGET_BIOSSEG 0x0f000 +- +-#define TARGET_CPU_086 0 +-#define TARGET_CPU_186 1 +-#define TARGET_CPU_286 2 +-#define TARGET_CPU_386 3 +-#define TARGET_CPU_486 4 +-#define TARGET_CPU_586 5 +- +-#define TARGET_VM86_SIGNAL 0 /* return due to signal */ +-#define TARGET_VM86_UNKNOWN 1 /* unhandled GP fault - IO-instruction or similar */ +-#define TARGET_VM86_INTx 2 /* int3/int x instruction (ARG = x) */ +-#define TARGET_VM86_STI 3 /* sti/popf/iret instruction enabled virtual interrupts */ +- +-/* +- * Additional return values when invoking new vm86() +- */ +-#define TARGET_VM86_PICRETURN 4 /* return due to pending PIC request */ +-#define TARGET_VM86_TRAP 6 /* return due to DOS-debugger request */ +- +-/* +- * function codes when invoking new vm86() +- */ +-#define TARGET_VM86_PLUS_INSTALL_CHECK 0 +-#define TARGET_VM86_ENTER 1 +-#define TARGET_VM86_ENTER_NO_BYPASS 2 +-#define TARGET_VM86_REQUEST_IRQ 3 +-#define TARGET_VM86_FREE_IRQ 4 +-#define TARGET_VM86_GET_IRQ_BITS 5 +-#define TARGET_VM86_GET_AND_RESET_IRQ 6 +- +-/* +- * This is the stack-layout seen by the user space program when we have +- * done a translation of "SAVE_ALL" from vm86 mode. The real kernel layout +- * is 'kernel_vm86_regs' (see below). +- */ +- +-struct target_vm86_regs { +-/* +- * normal regs, with special meaning for the segment descriptors.. +- */ +- abi_long ebx; +- abi_long ecx; +- abi_long edx; +- abi_long esi; +- abi_long edi; +- abi_long ebp; +- abi_long eax; +- abi_long __null_ds; +- abi_long __null_es; +- abi_long __null_fs; +- abi_long __null_gs; +- abi_long orig_eax; +- abi_long eip; +- unsigned short cs, __csh; +- abi_long eflags; +- abi_long esp; +- unsigned short ss, __ssh; +-/* +- * these are specific to v86 mode: +- */ +- unsigned short es, __esh; +- unsigned short ds, __dsh; +- unsigned short fs, __fsh; +- unsigned short gs, __gsh; +-}; +- +-struct target_revectored_struct { +- abi_ulong __map[8]; /* 256 bits */ +-}; +- +-struct target_vm86_struct { +- struct target_vm86_regs regs; +- abi_ulong flags; +- abi_ulong screen_bitmap; +- abi_ulong cpu_type; +- struct target_revectored_struct int_revectored; +- struct target_revectored_struct int21_revectored; +-}; +- +-/* +- * flags masks +- */ +-#define TARGET_VM86_SCREEN_BITMAP 0x0001 +- +-struct target_vm86plus_info_struct { +- abi_ulong flags; +-#define TARGET_force_return_for_pic (1 << 0) +-#define TARGET_vm86dbg_active (1 << 1) /* for debugger */ +-#define TARGET_vm86dbg_TFpendig (1 << 2) /* for debugger */ +-#define TARGET_is_vm86pus (1 << 31) /* for vm86 internal use */ +- unsigned char vm86dbg_intxxtab[32]; /* for debugger */ +-}; +- +-struct target_vm86plus_struct { +- struct target_vm86_regs regs; +- abi_ulong flags; +- abi_ulong screen_bitmap; +- abi_ulong cpu_type; +- struct target_revectored_struct int_revectored; +- struct target_revectored_struct int21_revectored; +- struct target_vm86plus_info_struct vm86plus; +-}; ++/* Increased to accomodate the high values, same as arch/x86/include/asm/segment.h */ ++#define TARGET_GDT_ENTRIES 32 + + #define UNAME_MACHINE "i686" + #define UNAME_MINIMUM_RELEASE "2.6.32" +diff --git a/home/gkrishna/Shelly/work/qemu/linux-user/i386/syscall_nr.h b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/i386/syscall_nr.h +index c8f7302..a956de9 100644 +--- a/home/gkrishna/Shelly/work/qemu/linux-user/i386/syscall_nr.h ++++ b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/i386/syscall_nr.h +@@ -2,354 +2,10 @@ + * This file contains the system call numbers. + */ + +-#define TARGET_NR_restart_syscall 0 +-#define TARGET_NR_exit 1 +-#define TARGET_NR_fork 2 +-#define TARGET_NR_read 3 +-#define TARGET_NR_write 4 +-#define TARGET_NR_open 5 +-#define TARGET_NR_close 6 +-#define TARGET_NR_waitpid 7 +-#define TARGET_NR_creat 8 +-#define TARGET_NR_link 9 +-#define TARGET_NR_unlink 10 +-#define TARGET_NR_execve 11 +-#define TARGET_NR_chdir 12 +-#define TARGET_NR_time 13 +-#define TARGET_NR_mknod 14 +-#define TARGET_NR_chmod 15 +-#define TARGET_NR_lchown 16 +-#define TARGET_NR_break 17 +-#define TARGET_NR_oldstat 18 +-#define TARGET_NR_lseek 19 +-#define TARGET_NR_getpid 20 +-#define TARGET_NR_mount 21 +-#define TARGET_NR_umount 22 +-#define TARGET_NR_setuid 23 +-#define TARGET_NR_getuid 24 +-#define TARGET_NR_stime 25 +-#define TARGET_NR_ptrace 26 +-#define TARGET_NR_alarm 27 +-#define TARGET_NR_oldfstat 28 +-#define TARGET_NR_pause 29 +-#define TARGET_NR_utime 30 +-#define TARGET_NR_stty 31 +-#define TARGET_NR_gtty 32 +-#define TARGET_NR_access 33 +-#define TARGET_NR_nice 34 +-#define TARGET_NR_ftime 35 +-#define TARGET_NR_sync 36 +-#define TARGET_NR_kill 37 +-#define TARGET_NR_rename 38 +-#define TARGET_NR_mkdir 39 +-#define TARGET_NR_rmdir 40 +-#define TARGET_NR_dup 41 +-#define TARGET_NR_pipe 42 +-#define TARGET_NR_times 43 +-#define TARGET_NR_prof 44 +-#define TARGET_NR_brk 45 +-#define TARGET_NR_setgid 46 +-#define TARGET_NR_getgid 47 +-#define TARGET_NR_signal 48 +-#define TARGET_NR_geteuid 49 +-#define TARGET_NR_getegid 50 +-#define TARGET_NR_acct 51 +-#define TARGET_NR_umount2 52 +-#define TARGET_NR_lock 53 +-#define TARGET_NR_ioctl 54 +-#define TARGET_NR_fcntl 55 +-#define TARGET_NR_mpx 56 +-#define TARGET_NR_setpgid 57 +-#define TARGET_NR_ulimit 58 +-#define TARGET_NR_oldolduname 59 +-#define TARGET_NR_umask 60 +-#define TARGET_NR_chroot 61 +-#define TARGET_NR_ustat 62 +-#define TARGET_NR_dup2 63 +-#define TARGET_NR_getppid 64 +-#define TARGET_NR_getpgrp 65 +-#define TARGET_NR_setsid 66 +-#define TARGET_NR_sigaction 67 +-#define TARGET_NR_sgetmask 68 +-#define TARGET_NR_ssetmask 69 +-#define TARGET_NR_setreuid 70 +-#define TARGET_NR_setregid 71 +-#define TARGET_NR_sigsuspend 72 +-#define TARGET_NR_sigpending 73 +-#define TARGET_NR_sethostname 74 +-#define TARGET_NR_setrlimit 75 +-#define TARGET_NR_getrlimit 76 /* Back compatible 2Gig limited rlimit */ +-#define TARGET_NR_getrusage 77 +-#define TARGET_NR_gettimeofday 78 +-#define TARGET_NR_settimeofday 79 +-#define TARGET_NR_getgroups 80 +-#define TARGET_NR_setgroups 81 +-#define TARGET_NR_select 82 +-#define TARGET_NR_symlink 83 +-#define TARGET_NR_oldlstat 84 +-#define TARGET_NR_readlink 85 +-#define TARGET_NR_uselib 86 +-#define TARGET_NR_swapon 87 +-#define TARGET_NR_reboot 88 +-#define TARGET_NR_readdir 89 +-#define TARGET_NR_mmap 90 +-#define TARGET_NR_munmap 91 +-#define TARGET_NR_truncate 92 +-#define TARGET_NR_ftruncate 93 +-#define TARGET_NR_fchmod 94 +-#define TARGET_NR_fchown 95 +-#define TARGET_NR_getpriority 96 +-#define TARGET_NR_setpriority 97 +-#define TARGET_NR_profil 98 +-#define TARGET_NR_statfs 99 +-#define TARGET_NR_fstatfs 100 +-#define TARGET_NR_ioperm 101 +-#define TARGET_NR_socketcall 102 +-#define TARGET_NR_syslog 103 +-#define TARGET_NR_setitimer 104 +-#define TARGET_NR_getitimer 105 +-#define TARGET_NR_stat 106 +-#define TARGET_NR_lstat 107 +-#define TARGET_NR_fstat 108 +-#define TARGET_NR_olduname 109 +-#define TARGET_NR_iopl 110 +-#define TARGET_NR_vhangup 111 +-#define TARGET_NR_idle 112 +-#define TARGET_NR_vm86old 113 +-#define TARGET_NR_wait4 114 +-#define TARGET_NR_swapoff 115 +-#define TARGET_NR_sysinfo 116 +-#define TARGET_NR_ipc 117 +-#define TARGET_NR_fsync 118 +-#define TARGET_NR_sigreturn 119 +-#define TARGET_NR_clone 120 +-#define TARGET_NR_setdomainname 121 +-#define TARGET_NR_uname 122 +-#define TARGET_NR_modify_ldt 123 +-#define TARGET_NR_adjtimex 124 +-#define TARGET_NR_mprotect 125 +-#define TARGET_NR_sigprocmask 126 +-#define TARGET_NR_create_module 127 +-#define TARGET_NR_init_module 128 +-#define TARGET_NR_delete_module 129 +-#define TARGET_NR_get_kernel_syms 130 +-#define TARGET_NR_quotactl 131 +-#define TARGET_NR_getpgid 132 +-#define TARGET_NR_fchdir 133 +-#define TARGET_NR_bdflush 134 +-#define TARGET_NR_sysfs 135 +-#define TARGET_NR_personality 136 +-#define TARGET_NR_afs_syscall 137 /* Syscall for Andrew File System */ +-#define TARGET_NR_setfsuid 138 +-#define TARGET_NR_setfsgid 139 +-#define TARGET_NR__llseek 140 +-#define TARGET_NR_getdents 141 +-#define TARGET_NR__newselect 142 +-#define TARGET_NR_flock 143 +-#define TARGET_NR_msync 144 +-#define TARGET_NR_readv 145 +-#define TARGET_NR_writev 146 +-#define TARGET_NR_getsid 147 +-#define TARGET_NR_fdatasync 148 +-#define TARGET_NR__sysctl 149 +-#define TARGET_NR_mlock 150 +-#define TARGET_NR_munlock 151 +-#define TARGET_NR_mlockall 152 +-#define TARGET_NR_munlockall 153 +-#define TARGET_NR_sched_setparam 154 +-#define TARGET_NR_sched_getparam 155 +-#define TARGET_NR_sched_setscheduler 156 +-#define TARGET_NR_sched_getscheduler 157 +-#define TARGET_NR_sched_yield 158 +-#define TARGET_NR_sched_get_priority_max 159 +-#define TARGET_NR_sched_get_priority_min 160 +-#define TARGET_NR_sched_rr_get_interval 161 +-#define TARGET_NR_nanosleep 162 +-#define TARGET_NR_mremap 163 +-#define TARGET_NR_setresuid 164 +-#define TARGET_NR_getresuid 165 +-#define TARGET_NR_vm86 166 +-#define TARGET_NR_query_module 167 +-#define TARGET_NR_poll 168 +-#define TARGET_NR_nfsservctl 169 +-#define TARGET_NR_setresgid 170 +-#define TARGET_NR_getresgid 171 +-#define TARGET_NR_prctl 172 +-#define TARGET_NR_rt_sigreturn 173 +-#define TARGET_NR_rt_sigaction 174 +-#define TARGET_NR_rt_sigprocmask 175 +-#define TARGET_NR_rt_sigpending 176 +-#define TARGET_NR_rt_sigtimedwait 177 +-#define TARGET_NR_rt_sigqueueinfo 178 +-#define TARGET_NR_rt_sigsuspend 179 +-#define TARGET_NR_pread64 180 +-#define TARGET_NR_pwrite64 181 +-#define TARGET_NR_chown 182 +-#define TARGET_NR_getcwd 183 +-#define TARGET_NR_capget 184 +-#define TARGET_NR_capset 185 +-#define TARGET_NR_sigaltstack 186 +-#define TARGET_NR_sendfile 187 +-#define TARGET_NR_getpmsg 188 /* some people actually want streams */ +-#define TARGET_NR_putpmsg 189 /* some people actually want streams */ +-#define TARGET_NR_vfork 190 +-#define TARGET_NR_ugetrlimit 191 /* SuS compliant getrlimit */ +-#define TARGET_NR_mmap2 192 +-#define TARGET_NR_truncate64 193 +-#define TARGET_NR_ftruncate64 194 +-#define TARGET_NR_stat64 195 +-#define TARGET_NR_lstat64 196 +-#define TARGET_NR_fstat64 197 +-#define TARGET_NR_lchown32 198 +-#define TARGET_NR_getuid32 199 +-#define TARGET_NR_getgid32 200 +-#define TARGET_NR_geteuid32 201 +-#define TARGET_NR_getegid32 202 +-#define TARGET_NR_setreuid32 203 +-#define TARGET_NR_setregid32 204 +-#define TARGET_NR_getgroups32 205 +-#define TARGET_NR_setgroups32 206 +-#define TARGET_NR_fchown32 207 +-#define TARGET_NR_setresuid32 208 +-#define TARGET_NR_getresuid32 209 +-#define TARGET_NR_setresgid32 210 +-#define TARGET_NR_getresgid32 211 +-#define TARGET_NR_chown32 212 +-#define TARGET_NR_setuid32 213 +-#define TARGET_NR_setgid32 214 +-#define TARGET_NR_setfsuid32 215 +-#define TARGET_NR_setfsgid32 216 +-#define TARGET_NR_pivot_root 217 +-#define TARGET_NR_mincore 218 +-#define TARGET_NR_madvise 219 +-#define TARGET_NR_madvise1 219 /* delete when C lib stub is removed */ +-#define TARGET_NR_getdents64 220 +-#define TARGET_NR_fcntl64 221 +-/* 223 is unused */ +-#define TARGET_NR_gettid 224 +-#define TARGET_NR_readahead 225 +-#define TARGET_NR_setxattr 226 +-#define TARGET_NR_lsetxattr 227 +-#define TARGET_NR_fsetxattr 228 +-#define TARGET_NR_getxattr 229 +-#define TARGET_NR_lgetxattr 230 +-#define TARGET_NR_fgetxattr 231 +-#define TARGET_NR_listxattr 232 +-#define TARGET_NR_llistxattr 233 +-#define TARGET_NR_flistxattr 234 +-#define TARGET_NR_removexattr 235 +-#define TARGET_NR_lremovexattr 236 +-#define TARGET_NR_fremovexattr 237 +-#define TARGET_NR_tkill 238 +-#define TARGET_NR_sendfile64 239 +-#define TARGET_NR_futex 240 +-#define TARGET_NR_sched_setaffinity 241 +-#define TARGET_NR_sched_getaffinity 242 +-#define TARGET_NR_set_thread_area 243 +-#define TARGET_NR_get_thread_area 244 +-#define TARGET_NR_io_setup 245 +-#define TARGET_NR_io_destroy 246 +-#define TARGET_NR_io_getevents 247 +-#define TARGET_NR_io_submit 248 +-#define TARGET_NR_io_cancel 249 +-#define TARGET_NR_fadvise64 250 +-/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */ +-#define TARGET_NR_exit_group 252 +-#define TARGET_NR_lookup_dcookie 253 +-#define TARGET_NR_epoll_create 254 +-#define TARGET_NR_epoll_ctl 255 +-#define TARGET_NR_epoll_wait 256 +-#define TARGET_NR_remap_file_pages 257 +-#define TARGET_NR_set_tid_address 258 +-#define TARGET_NR_timer_create 259 +-#define TARGET_NR_timer_settime (TARGET_NR_timer_create+1) +-#define TARGET_NR_timer_gettime (TARGET_NR_timer_create+2) +-#define TARGET_NR_timer_getoverrun (TARGET_NR_timer_create+3) +-#define TARGET_NR_timer_delete (TARGET_NR_timer_create+4) +-#define TARGET_NR_clock_settime (TARGET_NR_timer_create+5) +-#define TARGET_NR_clock_gettime (TARGET_NR_timer_create+6) +-#define TARGET_NR_clock_getres (TARGET_NR_timer_create+7) +-#define TARGET_NR_clock_nanosleep (TARGET_NR_timer_create+8) +-#define TARGET_NR_statfs64 268 +-#define TARGET_NR_fstatfs64 269 +-#define TARGET_NR_tgkill 270 +-#define TARGET_NR_utimes 271 +-#define TARGET_NR_fadvise64_64 272 +-#define TARGET_NR_vserver 273 +-#define TARGET_NR_mbind 274 +-#define TARGET_NR_get_mempolicy 275 +-#define TARGET_NR_set_mempolicy 276 +-#define TARGET_NR_mq_open 277 +-#define TARGET_NR_mq_unlink (TARGET_NR_mq_open+1) +-#define TARGET_NR_mq_timedsend (TARGET_NR_mq_open+2) +-#define TARGET_NR_mq_timedreceive (TARGET_NR_mq_open+3) +-#define TARGET_NR_mq_notify (TARGET_NR_mq_open+4) +-#define TARGET_NR_mq_getsetattr (TARGET_NR_mq_open+5) +-#define TARGET_NR_kexec_load 283 +-#define TARGET_NR_waitid 284 +-/* #define TARGET_NR_sys_setaltroot 285 */ +-#define TARGET_NR_add_key 286 +-#define TARGET_NR_request_key 287 +-#define TARGET_NR_keyctl 288 +-#define TARGET_NR_ioprio_set 289 +-#define TARGET_NR_ioprio_get 290 +-#define TARGET_NR_inotify_init 291 +-#define TARGET_NR_inotify_add_watch 292 +-#define TARGET_NR_inotify_rm_watch 293 +-#define TARGET_NR_migrate_pages 294 +-#define TARGET_NR_openat 295 +-#define TARGET_NR_mkdirat 296 +-#define TARGET_NR_mknodat 297 +-#define TARGET_NR_fchownat 298 +-#define TARGET_NR_futimesat 299 +-#define TARGET_NR_fstatat64 300 +-#define TARGET_NR_unlinkat 301 +-#define TARGET_NR_renameat 302 +-#define TARGET_NR_linkat 303 +-#define TARGET_NR_symlinkat 304 +-#define TARGET_NR_readlinkat 305 +-#define TARGET_NR_fchmodat 306 +-#define TARGET_NR_faccessat 307 +-#define TARGET_NR_pselect6 308 +-#define TARGET_NR_ppoll 309 +-#define TARGET_NR_unshare 310 +-#define TARGET_NR_set_robust_list 311 +-#define TARGET_NR_get_robust_list 312 +-#define TARGET_NR_splice 313 +-#define TARGET_NR_sync_file_range 314 +-#define TARGET_NR_tee 315 +-#define TARGET_NR_vmsplice 316 +-#define TARGET_NR_move_pages 317 +-#define TARGET_NR_getcpu 318 +-#define TARGET_NR_epoll_pwait 319 +-#define TARGET_NR_utimensat 320 +-#define TARGET_NR_signalfd 321 +-#define TARGET_NR_timerfd 322 +-#define TARGET_NR_eventfd 323 +-#define TARGET_NR_fallocate 324 +-#define TARGET_NR_timerfd_settime 325 +-#define TARGET_NR_timerfd_gettime 326 +-#define TARGET_NR_signalfd4 327 +-#define TARGET_NR_eventfd2 328 +-#define TARGET_NR_epoll_create1 329 +-#define TARGET_NR_dup3 330 +-#define TARGET_NR_pipe2 331 +-#define TARGET_NR_inotify_init1 332 +-#define TARGET_NR_preadv 333 +-#define TARGET_NR_pwritev 334 +-#define TARGET_NR_rt_tgsigqueueinfo 335 +-#define TARGET_NR_perf_event_open 336 +-#define TARGET_NR_recvmmsg 337 +-#define TARGET_NR_fanotify_init 338 +-#define TARGET_NR_fanotify_mark 339 +-#define TARGET_NR_prlimit64 340 +-#define TARGET_NR_name_to_handle_at 341 +-#define TARGET_NR_open_by_handle_at 342 +-#define TARGET_NR_clock_adjtime 343 +-#define TARGET_NR_syncfs 344 +-#define TARGET_NR_sendmmsg 345 +-#define TARGET_NR_setns 346 +-#define TARGET_NR_process_vm_readv 347 +-#define TARGET_NR_process_vm_writev 348 +-#define TARGET_NR_kcmp 349 +-#define TARGET_NR_finit_module 350 ++#define TARGET_NR_terminate 1 ++#define TARGET_NR_transmit 2 ++#define TARGET_NR_receive 3 ++#define TARGET_NR_fdwait 4 ++#define TARGET_NR_allocate 5 ++#define TARGET_NR_deallocate 6 ++#define TARGET_NR_random 7 +diff --git a/home/gkrishna/Shelly/work/qemu/linux-user/linuxload.c b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/linuxload.c +index 506e837..515a382 100644 +--- a/home/gkrishna/Shelly/work/qemu/linux-user/linuxload.c ++++ b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/linuxload.c +@@ -5,13 +5,19 @@ + #include + #include + #include ++#include + #include + #include ++#include + + #include "qemu.h" ++#include "flag.h" + + #define NGROUPS 32 + ++char *magicdump_filename = NULL, *magicpregen_filename = NULL; ++extern int seed_passed; ++ + /* ??? This should really be somewhere else. */ + abi_long memcpy_to_target(abi_ulong dest, const void *src, + unsigned long len) +@@ -26,17 +32,6 @@ abi_long memcpy_to_target(abi_ulong dest, const void *src, + return 0; + } + +-static int count(char ** vec) +-{ +- int i; +- +- for(i = 0; *vec; i++) { +- vec++; +- } +- +- return(i); +-} +- + static int prepare_binprm(struct linux_binprm *bprm) + { + struct stat st; +@@ -134,39 +129,93 @@ int loader_exec(int fdexec, const char *filename, char **argv, char **envp, + struct target_pt_regs * regs, struct image_info *infop, + struct linux_binprm *bprm) + { ++ int magic_fd = -1; + int retval; + int i; + +- bprm->p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int); +- memset(bprm->page, 0, sizeof(bprm->page)); ++ bprm->p = 0; // TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int); ++ //memset(bprm->page, 0, sizeof(bprm->page)); + bprm->fd = fdexec; + bprm->filename = (char *)filename; +- bprm->argc = count(argv); +- bprm->argv = argv; +- bprm->envc = count(envp); +- bprm->envp = envp; ++ ++ assert(argv == NULL); assert(envp == NULL); ++ bprm->argc = 0; ++ bprm->argv = NULL; ++ bprm->envc = 0; ++ bprm->envp = NULL; + + retval = prepare_binprm(bprm); + + if(retval>=0) { + if (bprm->buf[0] == 0x7f +- && bprm->buf[1] == 'E' +- && bprm->buf[2] == 'L' +- && bprm->buf[3] == 'F') { ++ && (bprm->buf[1] == 'E' || bprm->buf[1] == 'C') ++ && (bprm->buf[2] == 'L' || bprm->buf[2] == 'G') ++ && (bprm->buf[3] == 'F' || bprm->buf[3] == 'C')) { + retval = load_elf_binary(bprm, infop); +-#if defined(TARGET_HAS_BFLT) +- } else if (bprm->buf[0] == 'b' +- && bprm->buf[1] == 'F' +- && bprm->buf[2] == 'L' +- && bprm->buf[3] == 'T') { +- retval = load_flt_binary(bprm, infop); +-#endif + } else { + return -ENOEXEC; + } + } + + if(retval>=0) { ++ abi_ulong error; ++ unsigned char temp_rand; ++ ++ error = target_mmap(CGC_MAGIC_PAGE_ADDR, TARGET_PAGE_SIZE, ++ PROT_READ | PROT_WRITE, ++ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, ++ -1, 0); ++ ++ if (error == -1) { ++ perror("mmap CGC magic page"); ++ exit(-1); ++ } ++ ++ if (magicpregen_filename == NULL) { ++ if (magicdump_filename != NULL) ++ { ++ magic_fd = open(magicdump_filename, O_WRONLY|O_CREAT, 0666); ++ if (magic_fd < 0) ++ fprintf(stderr, "failed to open file %s for magicdump: %s", ++ magicdump_filename, ++ strerror(errno)); ++ } ++ for(i=0; i < TARGET_PAGE_SIZE / sizeof(unsigned char); i++) ++ { ++ if (seed_passed) ++ temp_rand = (unsigned char) (rand() % 0xff); ++ else ++ temp_rand = PRECONFIGURED_FLAG[i]; ++ ++ memcpy_to_target(CGC_MAGIC_PAGE_ADDR+(i*sizeof(unsigned char)), ++ &temp_rand, sizeof(unsigned char)); ++ if (!(magic_fd < 0)) ++ { ++ if (write(magic_fd, &temp_rand, sizeof(unsigned char)) != sizeof(unsigned char)) ++ { ++ fprintf(stderr, "error writing to magicdump file %s", strerror(errno)); ++ return -1; ++ } ++ } ++ } ++ } else { ++ int magicpregen_fd = open(magicpregen_filename, O_RDONLY); ++ if (magicpregen_fd < 0) ++ err(2,"Couldn't open the flag page content file"); ++ for (i = 0; i < 4096; i++) { ++ unsigned char c; ++ if (read(magicpregen_fd, &c, 1) != 1) ++ err(3,"Couldn't read from the flag page content file"); ++ memcpy_to_target(CGC_MAGIC_PAGE_ADDR+i, &c, 1); ++ } ++ close(magicpregen_fd); ++ } ++ ++ target_mprotect(CGC_MAGIC_PAGE_ADDR, TARGET_PAGE_SIZE, PROT_READ); ++ close(magic_fd); ++ } ++ ++ if(retval>=0) { + /* success. Initialize important registers */ + do_init_thread(regs, infop); + return retval; +diff --git a/home/gkrishna/Shelly/work/qemu/linux-user/main.c b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/main.c +index a8adb04..f2a3123 100644 +--- a/home/gkrishna/Shelly/work/qemu/linux-user/main.c ++++ b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/main.c +@@ -20,11 +20,13 @@ + #include + #include + #include ++#include + #include + #include + #include + #include + #include ++#include + + #include "qemu.h" + #include "qemu-common.h" +@@ -36,16 +38,19 @@ + + char *exec_path; + ++int bitflip; ++ + int singlestep; + const char *filename; +-const char *argv0; ++//const char *argv0; + int gdbstub_port; +-envlist_t *envlist; ++//envlist_t *envlist; + static const char *cpu_model; + unsigned long mmap_min_addr; + #if defined(CONFIG_USE_GUEST_BASE) + unsigned long guest_base; + int have_guest_base; ++int seed_passed = 0; + #if (TARGET_LONG_BITS == 32) && (HOST_LONG_BITS == 64) + /* + * When running 32-on-64 we should make sure we can fit all of the possible +@@ -54,16 +59,20 @@ int have_guest_base; + * This way we will never overlap with our own libraries or binaries or stack + * or anything else that QEMU maps. + */ +-# ifdef TARGET_MIPS +-/* MIPS only supports 31 bits of virtual address space for user space */ +-unsigned long reserved_va = 0x77000000; +-# else +-unsigned long reserved_va = 0xf7000000; +-# endif ++//static const unsigned long reserved_va = 0xf7000000; + #else +-unsigned long reserved_va; ++#error 32-on-64 only ++#endif + #endif ++ ++#define CGC_IDT_BASE 0x1000 ++ ++#ifdef TRACER ++extern char *predump_file; + #endif ++extern int enabled_double_empty_exiting; ++extern int report_bad_args; ++extern FILE *receive_count_fp; + + static void usage(void); + +@@ -73,7 +82,10 @@ const char *qemu_uname_release; + /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so + we allocate a bigger stack. Need a better solution, for example + by remapping the process stack directly at the right place */ +-unsigned long guest_stack_size = 8 * 1024 * 1024UL; ++ ++/* This is the size required to get the same stack mapping as the ++ CGC CQE VM */ ++//const unsigned long guest_stack_size = 8 * 1024 * 1024; + + void gemu_log(const char *fmt, ...) + { +@@ -211,7 +223,10 @@ void cpu_list_unlock(void) + } + + +-#ifdef TARGET_I386 ++#if !defined(TARGET_I386) || defined(TARGET_X86_64) ++#error "CGC is an old style, x86-only 32-bit world." ++#endif ++ + /***********************************************************/ + /* CPUX86 core interface */ + +@@ -239,23 +254,7 @@ static void write_dt(void *ptr, unsigned long addr, unsigned long limit, + + static uint64_t *idt_table; + #ifdef TARGET_X86_64 +-static void set_gate64(void *ptr, unsigned int type, unsigned int dpl, +- uint64_t addr, unsigned int sel) +-{ +- uint32_t *p, e1, e2; +- e1 = (addr & 0xffff) | (sel << 16); +- e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8); +- p = ptr; +- p[0] = tswap32(e1); +- p[1] = tswap32(e2); +- p[2] = tswap32(addr >> 32); +- p[3] = 0; +-} +-/* only dpl matters as we do only user space emulation */ +-static void set_idt(int n, unsigned int dpl) +-{ +- set_gate64(idt_table + n * 2, 0, dpl, 0, 0); +-} ++#error removed + #else + static void set_gate(void *ptr, unsigned int type, unsigned int dpl, + uint32_t addr, unsigned int sel) +@@ -299,20 +298,6 @@ void cpu_loop(CPUX86State *env) + env->regs[R_EBP], + 0, 0); + break; +-#ifndef TARGET_ABI32 +- case EXCP_SYSCALL: +- /* linux syscall from syscall instruction */ +- env->regs[R_EAX] = do_syscall(env, +- env->regs[R_EAX], +- env->regs[R_EDI], +- env->regs[R_ESI], +- env->regs[R_EDX], +- env->regs[10], +- env->regs[8], +- env->regs[9], +- 0, 0); +- break; +-#endif + case EXCP0B_NOSEG: + case EXCP0C_STACK: + info.si_signo = TARGET_SIGBUS; +@@ -322,12 +307,7 @@ void cpu_loop(CPUX86State *env) + queue_signal(env, info.si_signo, &info); + break; + case EXCP0D_GPF: +- /* XXX: potential problem if ABI32 */ +-#ifndef TARGET_X86_64 +- if (env->eflags & VM_MASK) { +- handle_vm86_fault(env); +- } else +-#endif ++ assert (!(env->eflags & VM_MASK)); /* Not _that_ old :) */ + { + info.si_signo = TARGET_SIGSEGV; + info.si_errno = 0; +@@ -347,3074 +327,81 @@ void cpu_loop(CPUX86State *env) + queue_signal(env, info.si_signo, &info); + break; + case EXCP00_DIVZ: +-#ifndef TARGET_X86_64 +- if (env->eflags & VM_MASK) { +- handle_vm86_trap(env, trapnr); +- } else +-#endif ++ assert (!(env->eflags & VM_MASK)); /* Not _that_ old :) */ + { + /* division by zero */ + info.si_signo = TARGET_SIGFPE; + info.si_errno = 0; +- info.si_code = TARGET_FPE_INTDIV; +- info._sifields._sigfault._addr = env->eip; +- queue_signal(env, info.si_signo, &info); +- } +- break; +- case EXCP01_DB: +- case EXCP03_INT3: +-#ifndef TARGET_X86_64 +- if (env->eflags & VM_MASK) { +- handle_vm86_trap(env, trapnr); +- } else +-#endif +- { +- info.si_signo = TARGET_SIGTRAP; +- info.si_errno = 0; +- if (trapnr == EXCP01_DB) { +- info.si_code = TARGET_TRAP_BRKPT; +- info._sifields._sigfault._addr = env->eip; +- } else { +- info.si_code = TARGET_SI_KERNEL; +- info._sifields._sigfault._addr = 0; +- } +- queue_signal(env, info.si_signo, &info); +- } +- break; +- case EXCP04_INTO: +- case EXCP05_BOUND: +-#ifndef TARGET_X86_64 +- if (env->eflags & VM_MASK) { +- handle_vm86_trap(env, trapnr); +- } else +-#endif +- { +- info.si_signo = TARGET_SIGSEGV; +- info.si_errno = 0; +- info.si_code = TARGET_SI_KERNEL; +- info._sifields._sigfault._addr = 0; +- queue_signal(env, info.si_signo, &info); +- } +- break; +- case EXCP06_ILLOP: +- info.si_signo = TARGET_SIGILL; +- info.si_errno = 0; +- info.si_code = TARGET_ILL_ILLOPN; +- info._sifields._sigfault._addr = env->eip; +- queue_signal(env, info.si_signo, &info); +- break; +- case EXCP_INTERRUPT: +- /* just indicate that signals should be handled asap */ +- break; +- case EXCP_DEBUG: +- { +- int sig; +- +- sig = gdb_handlesig(cs, TARGET_SIGTRAP); +- if (sig) +- { +- info.si_signo = sig; +- info.si_errno = 0; +- info.si_code = TARGET_TRAP_BRKPT; +- queue_signal(env, info.si_signo, &info); +- } +- } +- break; +- default: +- pc = env->segs[R_CS].base + env->eip; +- fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n", +- (long)pc, trapnr); +- abort(); +- } +- process_pending_signals(env); +- } +-} +-#endif +- +-#ifdef TARGET_ARM +- +-#define get_user_code_u32(x, gaddr, doswap) \ +- ({ abi_long __r = get_user_u32((x), (gaddr)); \ +- if (!__r && (doswap)) { \ +- (x) = bswap32(x); \ +- } \ +- __r; \ +- }) +- +-#define get_user_code_u16(x, gaddr, doswap) \ +- ({ abi_long __r = get_user_u16((x), (gaddr)); \ +- if (!__r && (doswap)) { \ +- (x) = bswap16(x); \ +- } \ +- __r; \ +- }) +- +-#ifdef TARGET_ABI32 +-/* Commpage handling -- there is no commpage for AArch64 */ +- +-/* +- * See the Linux kernel's Documentation/arm/kernel_user_helpers.txt +- * Input: +- * r0 = pointer to oldval +- * r1 = pointer to newval +- * r2 = pointer to target value +- * +- * Output: +- * r0 = 0 if *ptr was changed, non-0 if no exchange happened +- * C set if *ptr was changed, clear if no exchange happened +- * +- * Note segv's in kernel helpers are a bit tricky, we can set the +- * data address sensibly but the PC address is just the entry point. +- */ +-static void arm_kernel_cmpxchg64_helper(CPUARMState *env) +-{ +- uint64_t oldval, newval, val; +- uint32_t addr, cpsr; +- target_siginfo_t info; +- +- /* Based on the 32 bit code in do_kernel_trap */ +- +- /* XXX: This only works between threads, not between processes. +- It's probably possible to implement this with native host +- operations. However things like ldrex/strex are much harder so +- there's not much point trying. */ +- start_exclusive(); +- cpsr = cpsr_read(env); +- addr = env->regs[2]; +- +- if (get_user_u64(oldval, env->regs[0])) { +- env->exception.vaddress = env->regs[0]; +- goto segv; +- }; +- +- if (get_user_u64(newval, env->regs[1])) { +- env->exception.vaddress = env->regs[1]; +- goto segv; +- }; +- +- if (get_user_u64(val, addr)) { +- env->exception.vaddress = addr; +- goto segv; +- } +- +- if (val == oldval) { +- val = newval; +- +- if (put_user_u64(val, addr)) { +- env->exception.vaddress = addr; +- goto segv; +- }; +- +- env->regs[0] = 0; +- cpsr |= CPSR_C; +- } else { +- env->regs[0] = -1; +- cpsr &= ~CPSR_C; +- } +- cpsr_write(env, cpsr, CPSR_C); +- end_exclusive(); +- return; +- +-segv: +- end_exclusive(); +- /* We get the PC of the entry address - which is as good as anything, +- on a real kernel what you get depends on which mode it uses. */ +- info.si_signo = TARGET_SIGSEGV; +- info.si_errno = 0; +- /* XXX: check env->error_code */ +- info.si_code = TARGET_SEGV_MAPERR; +- info._sifields._sigfault._addr = env->exception.vaddress; +- queue_signal(env, info.si_signo, &info); +-} +- +-/* Handle a jump to the kernel code page. */ +-static int +-do_kernel_trap(CPUARMState *env) +-{ +- uint32_t addr; +- uint32_t cpsr; +- uint32_t val; +- +- switch (env->regs[15]) { +- case 0xffff0fa0: /* __kernel_memory_barrier */ +- /* ??? No-op. Will need to do better for SMP. */ +- break; +- case 0xffff0fc0: /* __kernel_cmpxchg */ +- /* XXX: This only works between threads, not between processes. +- It's probably possible to implement this with native host +- operations. However things like ldrex/strex are much harder so +- there's not much point trying. */ +- start_exclusive(); +- cpsr = cpsr_read(env); +- addr = env->regs[2]; +- /* FIXME: This should SEGV if the access fails. */ +- if (get_user_u32(val, addr)) +- val = ~env->regs[0]; +- if (val == env->regs[0]) { +- val = env->regs[1]; +- /* FIXME: Check for segfaults. */ +- put_user_u32(val, addr); +- env->regs[0] = 0; +- cpsr |= CPSR_C; +- } else { +- env->regs[0] = -1; +- cpsr &= ~CPSR_C; +- } +- cpsr_write(env, cpsr, CPSR_C); +- end_exclusive(); +- break; +- case 0xffff0fe0: /* __kernel_get_tls */ +- env->regs[0] = cpu_get_tls(env); +- break; +- case 0xffff0f60: /* __kernel_cmpxchg64 */ +- arm_kernel_cmpxchg64_helper(env); +- break; +- +- default: +- return 1; +- } +- /* Jump back to the caller. */ +- addr = env->regs[14]; +- if (addr & 1) { +- env->thumb = 1; +- addr &= ~1; +- } +- env->regs[15] = addr; +- +- return 0; +-} +- +-/* Store exclusive handling for AArch32 */ +-static int do_strex(CPUARMState *env) +-{ +- uint64_t val; +- int size; +- int rc = 1; +- int segv = 0; +- uint32_t addr; +- start_exclusive(); +- if (env->exclusive_addr != env->exclusive_test) { +- goto fail; +- } +- /* We know we're always AArch32 so the address is in uint32_t range +- * unless it was the -1 exclusive-monitor-lost value (which won't +- * match exclusive_test above). +- */ +- assert(extract64(env->exclusive_addr, 32, 32) == 0); +- addr = env->exclusive_addr; +- size = env->exclusive_info & 0xf; +- switch (size) { +- case 0: +- segv = get_user_u8(val, addr); +- break; +- case 1: +- segv = get_user_u16(val, addr); +- break; +- case 2: +- case 3: +- segv = get_user_u32(val, addr); +- break; +- default: +- abort(); +- } +- if (segv) { +- env->exception.vaddress = addr; +- goto done; +- } +- if (size == 3) { +- uint32_t valhi; +- segv = get_user_u32(valhi, addr + 4); +- if (segv) { +- env->exception.vaddress = addr + 4; +- goto done; +- } +- val = deposit64(val, 32, 32, valhi); +- } +- if (val != env->exclusive_val) { +- goto fail; +- } +- +- val = env->regs[(env->exclusive_info >> 8) & 0xf]; +- switch (size) { +- case 0: +- segv = put_user_u8(val, addr); +- break; +- case 1: +- segv = put_user_u16(val, addr); +- break; +- case 2: +- case 3: +- segv = put_user_u32(val, addr); +- break; +- } +- if (segv) { +- env->exception.vaddress = addr; +- goto done; +- } +- if (size == 3) { +- val = env->regs[(env->exclusive_info >> 12) & 0xf]; +- segv = put_user_u32(val, addr + 4); +- if (segv) { +- env->exception.vaddress = addr + 4; +- goto done; +- } +- } +- rc = 0; +-fail: +- env->regs[15] += 4; +- env->regs[(env->exclusive_info >> 4) & 0xf] = rc; +-done: +- end_exclusive(); +- return segv; +-} +- +-void cpu_loop(CPUARMState *env) +-{ +- CPUState *cs = CPU(arm_env_get_cpu(env)); +- int trapnr; +- unsigned int n, insn; +- target_siginfo_t info; +- uint32_t addr; +- +- for(;;) { +- cpu_exec_start(cs); +- trapnr = cpu_arm_exec(env); +- cpu_exec_end(cs); +- switch(trapnr) { +- case EXCP_UDEF: +- { +- TaskState *ts = cs->opaque; +- uint32_t opcode; +- int rc; +- +- /* we handle the FPU emulation here, as Linux */ +- /* we get the opcode */ +- /* FIXME - what to do if get_user() fails? */ +- get_user_code_u32(opcode, env->regs[15], env->bswap_code); +- +- rc = EmulateAll(opcode, &ts->fpa, env); +- if (rc == 0) { /* illegal instruction */ +- info.si_signo = TARGET_SIGILL; +- info.si_errno = 0; +- info.si_code = TARGET_ILL_ILLOPN; +- info._sifields._sigfault._addr = env->regs[15]; +- queue_signal(env, info.si_signo, &info); +- } else if (rc < 0) { /* FP exception */ +- int arm_fpe=0; +- +- /* translate softfloat flags to FPSR flags */ +- if (-rc & float_flag_invalid) +- arm_fpe |= BIT_IOC; +- if (-rc & float_flag_divbyzero) +- arm_fpe |= BIT_DZC; +- if (-rc & float_flag_overflow) +- arm_fpe |= BIT_OFC; +- if (-rc & float_flag_underflow) +- arm_fpe |= BIT_UFC; +- if (-rc & float_flag_inexact) +- arm_fpe |= BIT_IXC; +- +- FPSR fpsr = ts->fpa.fpsr; +- //printf("fpsr 0x%x, arm_fpe 0x%x\n",fpsr,arm_fpe); +- +- if (fpsr & (arm_fpe << 16)) { /* exception enabled? */ +- info.si_signo = TARGET_SIGFPE; +- info.si_errno = 0; +- +- /* ordered by priority, least first */ +- if (arm_fpe & BIT_IXC) info.si_code = TARGET_FPE_FLTRES; +- if (arm_fpe & BIT_UFC) info.si_code = TARGET_FPE_FLTUND; +- if (arm_fpe & BIT_OFC) info.si_code = TARGET_FPE_FLTOVF; +- if (arm_fpe & BIT_DZC) info.si_code = TARGET_FPE_FLTDIV; +- if (arm_fpe & BIT_IOC) info.si_code = TARGET_FPE_FLTINV; +- +- info._sifields._sigfault._addr = env->regs[15]; +- queue_signal(env, info.si_signo, &info); +- } else { +- env->regs[15] += 4; +- } +- +- /* accumulate unenabled exceptions */ +- if ((!(fpsr & BIT_IXE)) && (arm_fpe & BIT_IXC)) +- fpsr |= BIT_IXC; +- if ((!(fpsr & BIT_UFE)) && (arm_fpe & BIT_UFC)) +- fpsr |= BIT_UFC; +- if ((!(fpsr & BIT_OFE)) && (arm_fpe & BIT_OFC)) +- fpsr |= BIT_OFC; +- if ((!(fpsr & BIT_DZE)) && (arm_fpe & BIT_DZC)) +- fpsr |= BIT_DZC; +- if ((!(fpsr & BIT_IOE)) && (arm_fpe & BIT_IOC)) +- fpsr |= BIT_IOC; +- ts->fpa.fpsr=fpsr; +- } else { /* everything OK */ +- /* increment PC */ +- env->regs[15] += 4; +- } +- } +- break; +- case EXCP_SWI: +- case EXCP_BKPT: +- { +- env->eabi = 1; +- /* system call */ +- if (trapnr == EXCP_BKPT) { +- if (env->thumb) { +- /* FIXME - what to do if get_user() fails? */ +- get_user_code_u16(insn, env->regs[15], env->bswap_code); +- n = insn & 0xff; +- env->regs[15] += 2; +- } else { +- /* FIXME - what to do if get_user() fails? */ +- get_user_code_u32(insn, env->regs[15], env->bswap_code); +- n = (insn & 0xf) | ((insn >> 4) & 0xff0); +- env->regs[15] += 4; +- } +- } else { +- if (env->thumb) { +- /* FIXME - what to do if get_user() fails? */ +- get_user_code_u16(insn, env->regs[15] - 2, +- env->bswap_code); +- n = insn & 0xff; +- } else { +- /* FIXME - what to do if get_user() fails? */ +- get_user_code_u32(insn, env->regs[15] - 4, +- env->bswap_code); +- n = insn & 0xffffff; +- } +- } +- +- if (n == ARM_NR_cacheflush) { +- /* nop */ +- } else if (n == ARM_NR_semihosting +- || n == ARM_NR_thumb_semihosting) { +- env->regs[0] = do_arm_semihosting (env); +- } else if (n == 0 || n >= ARM_SYSCALL_BASE || env->thumb) { +- /* linux syscall */ +- if (env->thumb || n == 0) { +- n = env->regs[7]; +- } else { +- n -= ARM_SYSCALL_BASE; +- env->eabi = 0; +- } +- if ( n > ARM_NR_BASE) { +- switch (n) { +- case ARM_NR_cacheflush: +- /* nop */ +- break; +- case ARM_NR_set_tls: +- cpu_set_tls(env, env->regs[0]); +- env->regs[0] = 0; +- break; +- case ARM_NR_breakpoint: +- env->regs[15] -= env->thumb ? 2 : 4; +- goto excp_debug; +- default: +- gemu_log("qemu: Unsupported ARM syscall: 0x%x\n", +- n); +- env->regs[0] = -TARGET_ENOSYS; +- break; +- } +- } else { +- env->regs[0] = do_syscall(env, +- n, +- env->regs[0], +- env->regs[1], +- env->regs[2], +- env->regs[3], +- env->regs[4], +- env->regs[5], +- 0, 0); +- } +- } else { +- goto error; +- } +- } +- break; +- case EXCP_INTERRUPT: +- /* just indicate that signals should be handled asap */ +- break; +- case EXCP_STREX: +- if (!do_strex(env)) { +- break; +- } +- /* fall through for segv */ +- case EXCP_PREFETCH_ABORT: +- case EXCP_DATA_ABORT: +- addr = env->exception.vaddress; +- { +- info.si_signo = TARGET_SIGSEGV; +- info.si_errno = 0; +- /* XXX: check env->error_code */ +- info.si_code = TARGET_SEGV_MAPERR; +- info._sifields._sigfault._addr = addr; +- queue_signal(env, info.si_signo, &info); +- } +- break; +- case EXCP_DEBUG: +- excp_debug: +- { +- int sig; +- +- sig = gdb_handlesig(cs, TARGET_SIGTRAP); +- if (sig) +- { +- info.si_signo = sig; +- info.si_errno = 0; +- info.si_code = TARGET_TRAP_BRKPT; +- queue_signal(env, info.si_signo, &info); +- } +- } +- break; +- case EXCP_KERNEL_TRAP: +- if (do_kernel_trap(env)) +- goto error; +- break; +- default: +- error: +- fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", +- trapnr); +- cpu_dump_state(cs, stderr, fprintf, 0); +- abort(); +- } +- process_pending_signals(env); +- } +-} +- +-#else +- +-/* +- * Handle AArch64 store-release exclusive +- * +- * rs = gets the status result of store exclusive +- * rt = is the register that is stored +- * rt2 = is the second register store (in STP) +- * +- */ +-static int do_strex_a64(CPUARMState *env) +-{ +- uint64_t val; +- int size; +- bool is_pair; +- int rc = 1; +- int segv = 0; +- uint64_t addr; +- int rs, rt, rt2; +- +- start_exclusive(); +- /* size | is_pair << 2 | (rs << 4) | (rt << 9) | (rt2 << 14)); */ +- size = extract32(env->exclusive_info, 0, 2); +- is_pair = extract32(env->exclusive_info, 2, 1); +- rs = extract32(env->exclusive_info, 4, 5); +- rt = extract32(env->exclusive_info, 9, 5); +- rt2 = extract32(env->exclusive_info, 14, 5); +- +- addr = env->exclusive_addr; +- +- if (addr != env->exclusive_test) { +- goto finish; +- } +- +- switch (size) { +- case 0: +- segv = get_user_u8(val, addr); +- break; +- case 1: +- segv = get_user_u16(val, addr); +- break; +- case 2: +- segv = get_user_u32(val, addr); +- break; +- case 3: +- segv = get_user_u64(val, addr); +- break; +- default: +- abort(); +- } +- if (segv) { +- env->exception.vaddress = addr; +- goto error; +- } +- if (val != env->exclusive_val) { +- goto finish; +- } +- if (is_pair) { +- if (size == 2) { +- segv = get_user_u32(val, addr + 4); +- } else { +- segv = get_user_u64(val, addr + 8); +- } +- if (segv) { +- env->exception.vaddress = addr + (size == 2 ? 4 : 8); +- goto error; +- } +- if (val != env->exclusive_high) { +- goto finish; +- } +- } +- /* handle the zero register */ +- val = rt == 31 ? 0 : env->xregs[rt]; +- switch (size) { +- case 0: +- segv = put_user_u8(val, addr); +- break; +- case 1: +- segv = put_user_u16(val, addr); +- break; +- case 2: +- segv = put_user_u32(val, addr); +- break; +- case 3: +- segv = put_user_u64(val, addr); +- break; +- } +- if (segv) { +- goto error; +- } +- if (is_pair) { +- /* handle the zero register */ +- val = rt2 == 31 ? 0 : env->xregs[rt2]; +- if (size == 2) { +- segv = put_user_u32(val, addr + 4); +- } else { +- segv = put_user_u64(val, addr + 8); +- } +- if (segv) { +- env->exception.vaddress = addr + (size == 2 ? 4 : 8); +- goto error; +- } +- } +- rc = 0; +-finish: +- env->pc += 4; +- /* rs == 31 encodes a write to the ZR, thus throwing away +- * the status return. This is rather silly but valid. +- */ +- if (rs < 31) { +- env->xregs[rs] = rc; +- } +-error: +- /* instruction faulted, PC does not advance */ +- /* either way a strex releases any exclusive lock we have */ +- env->exclusive_addr = -1; +- end_exclusive(); +- return segv; +-} +- +-/* AArch64 main loop */ +-void cpu_loop(CPUARMState *env) +-{ +- CPUState *cs = CPU(arm_env_get_cpu(env)); +- int trapnr, sig; +- target_siginfo_t info; +- +- for (;;) { +- cpu_exec_start(cs); +- trapnr = cpu_arm_exec(env); +- cpu_exec_end(cs); +- +- switch (trapnr) { +- case EXCP_SWI: +- env->xregs[0] = do_syscall(env, +- env->xregs[8], +- env->xregs[0], +- env->xregs[1], +- env->xregs[2], +- env->xregs[3], +- env->xregs[4], +- env->xregs[5], +- 0, 0); +- break; +- case EXCP_INTERRUPT: +- /* just indicate that signals should be handled asap */ +- break; +- case EXCP_UDEF: +- info.si_signo = TARGET_SIGILL; +- info.si_errno = 0; +- info.si_code = TARGET_ILL_ILLOPN; +- info._sifields._sigfault._addr = env->pc; +- queue_signal(env, info.si_signo, &info); +- break; +- case EXCP_STREX: +- if (!do_strex_a64(env)) { +- break; +- } +- /* fall through for segv */ +- case EXCP_PREFETCH_ABORT: +- case EXCP_DATA_ABORT: +- info.si_signo = TARGET_SIGSEGV; +- info.si_errno = 0; +- /* XXX: check env->error_code */ +- info.si_code = TARGET_SEGV_MAPERR; +- info._sifields._sigfault._addr = env->exception.vaddress; +- queue_signal(env, info.si_signo, &info); +- break; +- case EXCP_DEBUG: +- case EXCP_BKPT: +- sig = gdb_handlesig(cs, TARGET_SIGTRAP); +- if (sig) { +- info.si_signo = sig; +- info.si_errno = 0; +- info.si_code = TARGET_TRAP_BRKPT; +- queue_signal(env, info.si_signo, &info); +- } +- break; +- default: +- fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", +- trapnr); +- cpu_dump_state(cs, stderr, fprintf, 0); +- abort(); +- } +- process_pending_signals(env); +- /* Exception return on AArch64 always clears the exclusive monitor, +- * so any return to running guest code implies this. +- * A strex (successful or otherwise) also clears the monitor, so +- * we don't need to specialcase EXCP_STREX. +- */ +- env->exclusive_addr = -1; +- } +-} +-#endif /* ndef TARGET_ABI32 */ +- +-#endif +- +-#ifdef TARGET_UNICORE32 +- +-void cpu_loop(CPUUniCore32State *env) +-{ +- CPUState *cs = CPU(uc32_env_get_cpu(env)); +- int trapnr; +- unsigned int n, insn; +- target_siginfo_t info; +- +- for (;;) { +- cpu_exec_start(cs); +- trapnr = uc32_cpu_exec(env); +- cpu_exec_end(cs); +- switch (trapnr) { +- case UC32_EXCP_PRIV: +- { +- /* system call */ +- get_user_u32(insn, env->regs[31] - 4); +- n = insn & 0xffffff; +- +- if (n >= UC32_SYSCALL_BASE) { +- /* linux syscall */ +- n -= UC32_SYSCALL_BASE; +- if (n == UC32_SYSCALL_NR_set_tls) { +- cpu_set_tls(env, env->regs[0]); +- env->regs[0] = 0; +- } else { +- env->regs[0] = do_syscall(env, +- n, +- env->regs[0], +- env->regs[1], +- env->regs[2], +- env->regs[3], +- env->regs[4], +- env->regs[5], +- 0, 0); +- } +- } else { +- goto error; +- } +- } +- break; +- case UC32_EXCP_DTRAP: +- case UC32_EXCP_ITRAP: +- info.si_signo = TARGET_SIGSEGV; +- info.si_errno = 0; +- /* XXX: check env->error_code */ +- info.si_code = TARGET_SEGV_MAPERR; +- info._sifields._sigfault._addr = env->cp0.c4_faultaddr; +- queue_signal(env, info.si_signo, &info); +- break; +- case EXCP_INTERRUPT: +- /* just indicate that signals should be handled asap */ +- break; +- case EXCP_DEBUG: +- { +- int sig; +- +- sig = gdb_handlesig(cs, TARGET_SIGTRAP); +- if (sig) { +- info.si_signo = sig; +- info.si_errno = 0; +- info.si_code = TARGET_TRAP_BRKPT; +- queue_signal(env, info.si_signo, &info); +- } +- } +- break; +- default: +- goto error; +- } +- process_pending_signals(env); +- } +- +-error: +- fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); +- cpu_dump_state(cs, stderr, fprintf, 0); +- abort(); +-} +-#endif +- +-#ifdef TARGET_SPARC +-#define SPARC64_STACK_BIAS 2047 +- +-//#define DEBUG_WIN +- +-/* WARNING: dealing with register windows _is_ complicated. More info +- can be found at http://www.sics.se/~psm/sparcstack.html */ +-static inline int get_reg_index(CPUSPARCState *env, int cwp, int index) +-{ +- index = (index + cwp * 16) % (16 * env->nwindows); +- /* wrap handling : if cwp is on the last window, then we use the +- registers 'after' the end */ +- if (index < 8 && env->cwp == env->nwindows - 1) +- index += 16 * env->nwindows; +- return index; +-} +- +-/* save the register window 'cwp1' */ +-static inline void save_window_offset(CPUSPARCState *env, int cwp1) +-{ +- unsigned int i; +- abi_ulong sp_ptr; +- +- sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)]; +-#ifdef TARGET_SPARC64 +- if (sp_ptr & 3) +- sp_ptr += SPARC64_STACK_BIAS; +-#endif +-#if defined(DEBUG_WIN) +- printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n", +- sp_ptr, cwp1); +-#endif +- for(i = 0; i < 16; i++) { +- /* FIXME - what to do if put_user() fails? */ +- put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr); +- sp_ptr += sizeof(abi_ulong); +- } +-} +- +-static void save_window(CPUSPARCState *env) +-{ +-#ifndef TARGET_SPARC64 +- unsigned int new_wim; +- new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) & +- ((1LL << env->nwindows) - 1); +- save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2)); +- env->wim = new_wim; +-#else +- save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2)); +- env->cansave++; +- env->canrestore--; +-#endif +-} +- +-static void restore_window(CPUSPARCState *env) +-{ +-#ifndef TARGET_SPARC64 +- unsigned int new_wim; +-#endif +- unsigned int i, cwp1; +- abi_ulong sp_ptr; +- +-#ifndef TARGET_SPARC64 +- new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) & +- ((1LL << env->nwindows) - 1); +-#endif +- +- /* restore the invalid window */ +- cwp1 = cpu_cwp_inc(env, env->cwp + 1); +- sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)]; +-#ifdef TARGET_SPARC64 +- if (sp_ptr & 3) +- sp_ptr += SPARC64_STACK_BIAS; +-#endif +-#if defined(DEBUG_WIN) +- printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n", +- sp_ptr, cwp1); +-#endif +- for(i = 0; i < 16; i++) { +- /* FIXME - what to do if get_user() fails? */ +- get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr); +- sp_ptr += sizeof(abi_ulong); +- } +-#ifdef TARGET_SPARC64 +- env->canrestore++; +- if (env->cleanwin < env->nwindows - 1) +- env->cleanwin++; +- env->cansave--; +-#else +- env->wim = new_wim; +-#endif +-} +- +-static void flush_windows(CPUSPARCState *env) +-{ +- int offset, cwp1; +- +- offset = 1; +- for(;;) { +- /* if restore would invoke restore_window(), then we can stop */ +- cwp1 = cpu_cwp_inc(env, env->cwp + offset); +-#ifndef TARGET_SPARC64 +- if (env->wim & (1 << cwp1)) +- break; +-#else +- if (env->canrestore == 0) +- break; +- env->cansave++; +- env->canrestore--; +-#endif +- save_window_offset(env, cwp1); +- offset++; +- } +- cwp1 = cpu_cwp_inc(env, env->cwp + 1); +-#ifndef TARGET_SPARC64 +- /* set wim so that restore will reload the registers */ +- env->wim = 1 << cwp1; +-#endif +-#if defined(DEBUG_WIN) +- printf("flush_windows: nb=%d\n", offset - 1); +-#endif +-} +- +-void cpu_loop (CPUSPARCState *env) +-{ +- CPUState *cs = CPU(sparc_env_get_cpu(env)); +- int trapnr; +- abi_long ret; +- target_siginfo_t info; +- +- while (1) { +- cpu_exec_start(cs); +- trapnr = cpu_sparc_exec (env); +- cpu_exec_end(cs); +- +- /* Compute PSR before exposing state. */ +- if (env->cc_op != CC_OP_FLAGS) { +- cpu_get_psr(env); +- } +- +- switch (trapnr) { +-#ifndef TARGET_SPARC64 +- case 0x88: +- case 0x90: +-#else +- case 0x110: +- case 0x16d: +-#endif +- ret = do_syscall (env, env->gregs[1], +- env->regwptr[0], env->regwptr[1], +- env->regwptr[2], env->regwptr[3], +- env->regwptr[4], env->regwptr[5], +- 0, 0); +- if ((abi_ulong)ret >= (abi_ulong)(-515)) { +-#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) +- env->xcc |= PSR_CARRY; +-#else +- env->psr |= PSR_CARRY; +-#endif +- ret = -ret; +- } else { +-#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) +- env->xcc &= ~PSR_CARRY; +-#else +- env->psr &= ~PSR_CARRY; +-#endif +- } +- env->regwptr[0] = ret; +- /* next instruction */ +- env->pc = env->npc; +- env->npc = env->npc + 4; +- break; +- case 0x83: /* flush windows */ +-#ifdef TARGET_ABI32 +- case 0x103: +-#endif +- flush_windows(env); +- /* next instruction */ +- env->pc = env->npc; +- env->npc = env->npc + 4; +- break; +-#ifndef TARGET_SPARC64 +- case TT_WIN_OVF: /* window overflow */ +- save_window(env); +- break; +- case TT_WIN_UNF: /* window underflow */ +- restore_window(env); +- break; +- case TT_TFAULT: +- case TT_DFAULT: +- { +- info.si_signo = TARGET_SIGSEGV; +- info.si_errno = 0; +- /* XXX: check env->error_code */ +- info.si_code = TARGET_SEGV_MAPERR; +- info._sifields._sigfault._addr = env->mmuregs[4]; +- queue_signal(env, info.si_signo, &info); +- } +- break; +-#else +- case TT_SPILL: /* window overflow */ +- save_window(env); +- break; +- case TT_FILL: /* window underflow */ +- restore_window(env); +- break; +- case TT_TFAULT: +- case TT_DFAULT: +- { +- info.si_signo = TARGET_SIGSEGV; +- info.si_errno = 0; +- /* XXX: check env->error_code */ +- info.si_code = TARGET_SEGV_MAPERR; +- if (trapnr == TT_DFAULT) +- info._sifields._sigfault._addr = env->dmmuregs[4]; +- else +- info._sifields._sigfault._addr = cpu_tsptr(env)->tpc; +- queue_signal(env, info.si_signo, &info); +- } +- break; +-#ifndef TARGET_ABI32 +- case 0x16e: +- flush_windows(env); +- sparc64_get_context(env); +- break; +- case 0x16f: +- flush_windows(env); +- sparc64_set_context(env); +- break; +-#endif +-#endif +- case EXCP_INTERRUPT: +- /* just indicate that signals should be handled asap */ +- break; +- case TT_ILL_INSN: +- { +- info.si_signo = TARGET_SIGILL; +- info.si_errno = 0; +- info.si_code = TARGET_ILL_ILLOPC; +- info._sifields._sigfault._addr = env->pc; +- queue_signal(env, info.si_signo, &info); +- } +- break; +- case EXCP_DEBUG: +- { +- int sig; +- +- sig = gdb_handlesig(cs, TARGET_SIGTRAP); +- if (sig) +- { +- info.si_signo = sig; +- info.si_errno = 0; +- info.si_code = TARGET_TRAP_BRKPT; +- queue_signal(env, info.si_signo, &info); +- } +- } +- break; +- default: +- printf ("Unhandled trap: 0x%x\n", trapnr); +- cpu_dump_state(cs, stderr, fprintf, 0); +- exit (1); +- } +- process_pending_signals (env); +- } +-} +- +-#endif +- +-#ifdef TARGET_PPC +-static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env) +-{ +- /* TO FIX */ +- return 0; +-} +- +-uint64_t cpu_ppc_load_tbl(CPUPPCState *env) +-{ +- return cpu_ppc_get_tb(env); +-} +- +-uint32_t cpu_ppc_load_tbu(CPUPPCState *env) +-{ +- return cpu_ppc_get_tb(env) >> 32; +-} +- +-uint64_t cpu_ppc_load_atbl(CPUPPCState *env) +-{ +- return cpu_ppc_get_tb(env); +-} +- +-uint32_t cpu_ppc_load_atbu(CPUPPCState *env) +-{ +- return cpu_ppc_get_tb(env) >> 32; +-} +- +-uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env) +-__attribute__ (( alias ("cpu_ppc_load_tbu") )); +- +-uint32_t cpu_ppc601_load_rtcl(CPUPPCState *env) +-{ +- return cpu_ppc_load_tbl(env) & 0x3FFFFF80; +-} +- +-/* XXX: to be fixed */ +-int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp) +-{ +- return -1; +-} +- +-int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val) +-{ +- return -1; +-} +- +-#define EXCP_DUMP(env, fmt, ...) \ +-do { \ +- CPUState *cs = ENV_GET_CPU(env); \ +- fprintf(stderr, fmt , ## __VA_ARGS__); \ +- cpu_dump_state(cs, stderr, fprintf, 0); \ +- qemu_log(fmt, ## __VA_ARGS__); \ +- if (qemu_log_enabled()) { \ +- log_cpu_state(cs, 0); \ +- } \ +-} while (0) +- +-static int do_store_exclusive(CPUPPCState *env) +-{ +- target_ulong addr; +- target_ulong page_addr; +- target_ulong val, val2 __attribute__((unused)) = 0; +- int flags; +- int segv = 0; +- +- addr = env->reserve_ea; +- page_addr = addr & TARGET_PAGE_MASK; +- start_exclusive(); +- mmap_lock(); +- flags = page_get_flags(page_addr); +- if ((flags & PAGE_READ) == 0) { +- segv = 1; +- } else { +- int reg = env->reserve_info & 0x1f; +- int size = env->reserve_info >> 5; +- int stored = 0; +- +- if (addr == env->reserve_addr) { +- switch (size) { +- case 1: segv = get_user_u8(val, addr); break; +- case 2: segv = get_user_u16(val, addr); break; +- case 4: segv = get_user_u32(val, addr); break; +-#if defined(TARGET_PPC64) +- case 8: segv = get_user_u64(val, addr); break; +- case 16: { +- segv = get_user_u64(val, addr); +- if (!segv) { +- segv = get_user_u64(val2, addr + 8); +- } +- break; +- } +-#endif +- default: abort(); +- } +- if (!segv && val == env->reserve_val) { +- val = env->gpr[reg]; +- switch (size) { +- case 1: segv = put_user_u8(val, addr); break; +- case 2: segv = put_user_u16(val, addr); break; +- case 4: segv = put_user_u32(val, addr); break; +-#if defined(TARGET_PPC64) +- case 8: segv = put_user_u64(val, addr); break; +- case 16: { +- if (val2 == env->reserve_val2) { +- if (msr_le) { +- val2 = val; +- val = env->gpr[reg+1]; +- } else { +- val2 = env->gpr[reg+1]; +- } +- segv = put_user_u64(val, addr); +- if (!segv) { +- segv = put_user_u64(val2, addr + 8); +- } +- } +- break; +- } +-#endif +- default: abort(); +- } +- if (!segv) { +- stored = 1; +- } +- } +- } +- env->crf[0] = (stored << 1) | xer_so; +- env->reserve_addr = (target_ulong)-1; +- } +- if (!segv) { +- env->nip += 4; +- } +- mmap_unlock(); +- end_exclusive(); +- return segv; +-} +- +-void cpu_loop(CPUPPCState *env) +-{ +- CPUState *cs = CPU(ppc_env_get_cpu(env)); +- target_siginfo_t info; +- int trapnr; +- target_ulong ret; +- +- for(;;) { +- cpu_exec_start(cs); +- trapnr = cpu_ppc_exec(env); +- cpu_exec_end(cs); +- switch(trapnr) { +- case POWERPC_EXCP_NONE: +- /* Just go on */ +- break; +- case POWERPC_EXCP_CRITICAL: /* Critical input */ +- cpu_abort(cs, "Critical interrupt while in user mode. " +- "Aborting\n"); +- break; +- case POWERPC_EXCP_MCHECK: /* Machine check exception */ +- cpu_abort(cs, "Machine check exception while in user mode. " +- "Aborting\n"); +- break; +- case POWERPC_EXCP_DSI: /* Data storage exception */ +- EXCP_DUMP(env, "Invalid data memory access: 0x" TARGET_FMT_lx "\n", +- env->spr[SPR_DAR]); +- /* XXX: check this. Seems bugged */ +- switch (env->error_code & 0xFF000000) { +- case 0x40000000: +- info.si_signo = TARGET_SIGSEGV; +- info.si_errno = 0; +- info.si_code = TARGET_SEGV_MAPERR; +- break; +- case 0x04000000: +- info.si_signo = TARGET_SIGILL; +- info.si_errno = 0; +- info.si_code = TARGET_ILL_ILLADR; +- break; +- case 0x08000000: +- info.si_signo = TARGET_SIGSEGV; +- info.si_errno = 0; +- info.si_code = TARGET_SEGV_ACCERR; +- break; +- default: +- /* Let's send a regular segfault... */ +- EXCP_DUMP(env, "Invalid segfault errno (%02x)\n", +- env->error_code); +- info.si_signo = TARGET_SIGSEGV; +- info.si_errno = 0; +- info.si_code = TARGET_SEGV_MAPERR; +- break; +- } +- info._sifields._sigfault._addr = env->nip; +- queue_signal(env, info.si_signo, &info); +- break; +- case POWERPC_EXCP_ISI: /* Instruction storage exception */ +- EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" TARGET_FMT_lx +- "\n", env->spr[SPR_SRR0]); +- /* XXX: check this */ +- switch (env->error_code & 0xFF000000) { +- case 0x40000000: +- info.si_signo = TARGET_SIGSEGV; +- info.si_errno = 0; +- info.si_code = TARGET_SEGV_MAPERR; +- break; +- case 0x10000000: +- case 0x08000000: +- info.si_signo = TARGET_SIGSEGV; +- info.si_errno = 0; +- info.si_code = TARGET_SEGV_ACCERR; +- break; +- default: +- /* Let's send a regular segfault... */ +- EXCP_DUMP(env, "Invalid segfault errno (%02x)\n", +- env->error_code); +- info.si_signo = TARGET_SIGSEGV; +- info.si_errno = 0; +- info.si_code = TARGET_SEGV_MAPERR; +- break; +- } +- info._sifields._sigfault._addr = env->nip - 4; +- queue_signal(env, info.si_signo, &info); +- break; +- case POWERPC_EXCP_EXTERNAL: /* External input */ +- cpu_abort(cs, "External interrupt while in user mode. " +- "Aborting\n"); +- break; +- case POWERPC_EXCP_ALIGN: /* Alignment exception */ +- EXCP_DUMP(env, "Unaligned memory access\n"); +- /* XXX: check this */ +- info.si_signo = TARGET_SIGBUS; +- info.si_errno = 0; +- info.si_code = TARGET_BUS_ADRALN; +- info._sifields._sigfault._addr = env->nip - 4; +- queue_signal(env, info.si_signo, &info); +- break; +- case POWERPC_EXCP_PROGRAM: /* Program exception */ +- /* XXX: check this */ +- switch (env->error_code & ~0xF) { +- case POWERPC_EXCP_FP: +- EXCP_DUMP(env, "Floating point program exception\n"); +- info.si_signo = TARGET_SIGFPE; +- info.si_errno = 0; +- switch (env->error_code & 0xF) { +- case POWERPC_EXCP_FP_OX: +- info.si_code = TARGET_FPE_FLTOVF; +- break; +- case POWERPC_EXCP_FP_UX: +- info.si_code = TARGET_FPE_FLTUND; +- break; +- case POWERPC_EXCP_FP_ZX: +- case POWERPC_EXCP_FP_VXZDZ: +- info.si_code = TARGET_FPE_FLTDIV; +- break; +- case POWERPC_EXCP_FP_XX: +- info.si_code = TARGET_FPE_FLTRES; +- break; +- case POWERPC_EXCP_FP_VXSOFT: +- info.si_code = TARGET_FPE_FLTINV; +- break; +- case POWERPC_EXCP_FP_VXSNAN: +- case POWERPC_EXCP_FP_VXISI: +- case POWERPC_EXCP_FP_VXIDI: +- case POWERPC_EXCP_FP_VXIMZ: +- case POWERPC_EXCP_FP_VXVC: +- case POWERPC_EXCP_FP_VXSQRT: +- case POWERPC_EXCP_FP_VXCVI: +- info.si_code = TARGET_FPE_FLTSUB; +- break; +- default: +- EXCP_DUMP(env, "Unknown floating point exception (%02x)\n", +- env->error_code); +- break; +- } +- break; +- case POWERPC_EXCP_INVAL: +- EXCP_DUMP(env, "Invalid instruction\n"); +- info.si_signo = TARGET_SIGILL; +- info.si_errno = 0; +- switch (env->error_code & 0xF) { +- case POWERPC_EXCP_INVAL_INVAL: +- info.si_code = TARGET_ILL_ILLOPC; +- break; +- case POWERPC_EXCP_INVAL_LSWX: +- info.si_code = TARGET_ILL_ILLOPN; +- break; +- case POWERPC_EXCP_INVAL_SPR: +- info.si_code = TARGET_ILL_PRVREG; +- break; +- case POWERPC_EXCP_INVAL_FP: +- info.si_code = TARGET_ILL_COPROC; +- break; +- default: +- EXCP_DUMP(env, "Unknown invalid operation (%02x)\n", +- env->error_code & 0xF); +- info.si_code = TARGET_ILL_ILLADR; +- break; +- } +- break; +- case POWERPC_EXCP_PRIV: +- EXCP_DUMP(env, "Privilege violation\n"); +- info.si_signo = TARGET_SIGILL; +- info.si_errno = 0; +- switch (env->error_code & 0xF) { +- case POWERPC_EXCP_PRIV_OPC: +- info.si_code = TARGET_ILL_PRVOPC; +- break; +- case POWERPC_EXCP_PRIV_REG: +- info.si_code = TARGET_ILL_PRVREG; +- break; +- default: +- EXCP_DUMP(env, "Unknown privilege violation (%02x)\n", +- env->error_code & 0xF); +- info.si_code = TARGET_ILL_PRVOPC; +- break; +- } +- break; +- case POWERPC_EXCP_TRAP: +- cpu_abort(cs, "Tried to call a TRAP\n"); +- break; +- default: +- /* Should not happen ! */ +- cpu_abort(cs, "Unknown program exception (%02x)\n", +- env->error_code); +- break; +- } +- info._sifields._sigfault._addr = env->nip - 4; +- queue_signal(env, info.si_signo, &info); +- break; +- case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ +- EXCP_DUMP(env, "No floating point allowed\n"); +- info.si_signo = TARGET_SIGILL; +- info.si_errno = 0; +- info.si_code = TARGET_ILL_COPROC; +- info._sifields._sigfault._addr = env->nip - 4; +- queue_signal(env, info.si_signo, &info); +- break; +- case POWERPC_EXCP_SYSCALL: /* System call exception */ +- cpu_abort(cs, "Syscall exception while in user mode. " +- "Aborting\n"); +- break; +- case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ +- EXCP_DUMP(env, "No APU instruction allowed\n"); +- info.si_signo = TARGET_SIGILL; +- info.si_errno = 0; +- info.si_code = TARGET_ILL_COPROC; +- info._sifields._sigfault._addr = env->nip - 4; +- queue_signal(env, info.si_signo, &info); +- break; +- case POWERPC_EXCP_DECR: /* Decrementer exception */ +- cpu_abort(cs, "Decrementer interrupt while in user mode. " +- "Aborting\n"); +- break; +- case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ +- cpu_abort(cs, "Fix interval timer interrupt while in user mode. " +- "Aborting\n"); +- break; +- case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ +- cpu_abort(cs, "Watchdog timer interrupt while in user mode. " +- "Aborting\n"); +- break; +- case POWERPC_EXCP_DTLB: /* Data TLB error */ +- cpu_abort(cs, "Data TLB exception while in user mode. " +- "Aborting\n"); +- break; +- case POWERPC_EXCP_ITLB: /* Instruction TLB error */ +- cpu_abort(cs, "Instruction TLB exception while in user mode. " +- "Aborting\n"); +- break; +- case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */ +- EXCP_DUMP(env, "No SPE/floating-point instruction allowed\n"); +- info.si_signo = TARGET_SIGILL; +- info.si_errno = 0; +- info.si_code = TARGET_ILL_COPROC; +- info._sifields._sigfault._addr = env->nip - 4; +- queue_signal(env, info.si_signo, &info); +- break; +- case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */ +- cpu_abort(cs, "Embedded floating-point data IRQ not handled\n"); +- break; +- case POWERPC_EXCP_EFPRI: /* Embedded floating-point round IRQ */ +- cpu_abort(cs, "Embedded floating-point round IRQ not handled\n"); +- break; +- case POWERPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */ +- cpu_abort(cs, "Performance monitor exception not handled\n"); +- break; +- case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */ +- cpu_abort(cs, "Doorbell interrupt while in user mode. " +- "Aborting\n"); +- break; +- case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */ +- cpu_abort(cs, "Doorbell critical interrupt while in user mode. " +- "Aborting\n"); +- break; +- case POWERPC_EXCP_RESET: /* System reset exception */ +- cpu_abort(cs, "Reset interrupt while in user mode. " +- "Aborting\n"); +- break; +- case POWERPC_EXCP_DSEG: /* Data segment exception */ +- cpu_abort(cs, "Data segment exception while in user mode. " +- "Aborting\n"); +- break; +- case POWERPC_EXCP_ISEG: /* Instruction segment exception */ +- cpu_abort(cs, "Instruction segment exception " +- "while in user mode. Aborting\n"); +- break; +- /* PowerPC 64 with hypervisor mode support */ +- case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ +- cpu_abort(cs, "Hypervisor decrementer interrupt " +- "while in user mode. Aborting\n"); +- break; +- case POWERPC_EXCP_TRACE: /* Trace exception */ +- /* Nothing to do: +- * we use this exception to emulate step-by-step execution mode. +- */ +- break; +- /* PowerPC 64 with hypervisor mode support */ +- case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ +- cpu_abort(cs, "Hypervisor data storage exception " +- "while in user mode. Aborting\n"); +- break; +- case POWERPC_EXCP_HISI: /* Hypervisor instruction storage excp */ +- cpu_abort(cs, "Hypervisor instruction storage exception " +- "while in user mode. Aborting\n"); +- break; +- case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */ +- cpu_abort(cs, "Hypervisor data segment exception " +- "while in user mode. Aborting\n"); +- break; +- case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment excp */ +- cpu_abort(cs, "Hypervisor instruction segment exception " +- "while in user mode. Aborting\n"); +- break; +- case POWERPC_EXCP_VPU: /* Vector unavailable exception */ +- EXCP_DUMP(env, "No Altivec instructions allowed\n"); +- info.si_signo = TARGET_SIGILL; +- info.si_errno = 0; +- info.si_code = TARGET_ILL_COPROC; +- info._sifields._sigfault._addr = env->nip - 4; +- queue_signal(env, info.si_signo, &info); +- break; +- case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */ +- cpu_abort(cs, "Programmable interval timer interrupt " +- "while in user mode. Aborting\n"); +- break; +- case POWERPC_EXCP_IO: /* IO error exception */ +- cpu_abort(cs, "IO error exception while in user mode. " +- "Aborting\n"); +- break; +- case POWERPC_EXCP_RUNM: /* Run mode exception */ +- cpu_abort(cs, "Run mode exception while in user mode. " +- "Aborting\n"); +- break; +- case POWERPC_EXCP_EMUL: /* Emulation trap exception */ +- cpu_abort(cs, "Emulation trap exception not handled\n"); +- break; +- case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ +- cpu_abort(cs, "Instruction fetch TLB exception " +- "while in user-mode. Aborting"); +- break; +- case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ +- cpu_abort(cs, "Data load TLB exception while in user-mode. " +- "Aborting"); +- break; +- case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ +- cpu_abort(cs, "Data store TLB exception while in user-mode. " +- "Aborting"); +- break; +- case POWERPC_EXCP_FPA: /* Floating-point assist exception */ +- cpu_abort(cs, "Floating-point assist exception not handled\n"); +- break; +- case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ +- cpu_abort(cs, "Instruction address breakpoint exception " +- "not handled\n"); +- break; +- case POWERPC_EXCP_SMI: /* System management interrupt */ +- cpu_abort(cs, "System management interrupt while in user mode. " +- "Aborting\n"); +- break; +- case POWERPC_EXCP_THERM: /* Thermal interrupt */ +- cpu_abort(cs, "Thermal interrupt interrupt while in user mode. " +- "Aborting\n"); +- break; +- case POWERPC_EXCP_PERFM: /* Embedded performance monitor IRQ */ +- cpu_abort(cs, "Performance monitor exception not handled\n"); +- break; +- case POWERPC_EXCP_VPUA: /* Vector assist exception */ +- cpu_abort(cs, "Vector assist exception not handled\n"); +- break; +- case POWERPC_EXCP_SOFTP: /* Soft patch exception */ +- cpu_abort(cs, "Soft patch exception not handled\n"); +- break; +- case POWERPC_EXCP_MAINT: /* Maintenance exception */ +- cpu_abort(cs, "Maintenance exception while in user mode. " +- "Aborting\n"); +- break; +- case POWERPC_EXCP_STOP: /* stop translation */ +- /* We did invalidate the instruction cache. Go on */ +- break; +- case POWERPC_EXCP_BRANCH: /* branch instruction: */ +- /* We just stopped because of a branch. Go on */ +- break; +- case POWERPC_EXCP_SYSCALL_USER: +- /* system call in user-mode emulation */ +- /* WARNING: +- * PPC ABI uses overflow flag in cr0 to signal an error +- * in syscalls. +- */ +- env->crf[0] &= ~0x1; +- ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4], +- env->gpr[5], env->gpr[6], env->gpr[7], +- env->gpr[8], 0, 0); +- if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) { +- /* Returning from a successful sigreturn syscall. +- Avoid corrupting register state. */ +- break; +- } +- if (ret > (target_ulong)(-515)) { +- env->crf[0] |= 0x1; +- ret = -ret; +- } +- env->gpr[3] = ret; +- break; +- case POWERPC_EXCP_STCX: +- if (do_store_exclusive(env)) { +- info.si_signo = TARGET_SIGSEGV; +- info.si_errno = 0; +- info.si_code = TARGET_SEGV_MAPERR; +- info._sifields._sigfault._addr = env->nip; +- queue_signal(env, info.si_signo, &info); +- } +- break; +- case EXCP_DEBUG: +- { +- int sig; +- +- sig = gdb_handlesig(cs, TARGET_SIGTRAP); +- if (sig) { +- info.si_signo = sig; +- info.si_errno = 0; +- info.si_code = TARGET_TRAP_BRKPT; +- queue_signal(env, info.si_signo, &info); +- } +- } +- break; +- case EXCP_INTERRUPT: +- /* just indicate that signals should be handled asap */ +- break; +- default: +- cpu_abort(cs, "Unknown exception 0x%d. Aborting\n", trapnr); +- break; +- } +- process_pending_signals(env); +- } +-} +-#endif +- +-#ifdef TARGET_MIPS +- +-# ifdef TARGET_ABI_MIPSO32 +-# define MIPS_SYS(name, args) args, +-static const uint8_t mips_syscall_args[] = { +- MIPS_SYS(sys_syscall , 8) /* 4000 */ +- MIPS_SYS(sys_exit , 1) +- MIPS_SYS(sys_fork , 0) +- MIPS_SYS(sys_read , 3) +- MIPS_SYS(sys_write , 3) +- MIPS_SYS(sys_open , 3) /* 4005 */ +- MIPS_SYS(sys_close , 1) +- MIPS_SYS(sys_waitpid , 3) +- MIPS_SYS(sys_creat , 2) +- MIPS_SYS(sys_link , 2) +- MIPS_SYS(sys_unlink , 1) /* 4010 */ +- MIPS_SYS(sys_execve , 0) +- MIPS_SYS(sys_chdir , 1) +- MIPS_SYS(sys_time , 1) +- MIPS_SYS(sys_mknod , 3) +- MIPS_SYS(sys_chmod , 2) /* 4015 */ +- MIPS_SYS(sys_lchown , 3) +- MIPS_SYS(sys_ni_syscall , 0) +- MIPS_SYS(sys_ni_syscall , 0) /* was sys_stat */ +- MIPS_SYS(sys_lseek , 3) +- MIPS_SYS(sys_getpid , 0) /* 4020 */ +- MIPS_SYS(sys_mount , 5) +- MIPS_SYS(sys_umount , 1) +- MIPS_SYS(sys_setuid , 1) +- MIPS_SYS(sys_getuid , 0) +- MIPS_SYS(sys_stime , 1) /* 4025 */ +- MIPS_SYS(sys_ptrace , 4) +- MIPS_SYS(sys_alarm , 1) +- MIPS_SYS(sys_ni_syscall , 0) /* was sys_fstat */ +- MIPS_SYS(sys_pause , 0) +- MIPS_SYS(sys_utime , 2) /* 4030 */ +- MIPS_SYS(sys_ni_syscall , 0) +- MIPS_SYS(sys_ni_syscall , 0) +- MIPS_SYS(sys_access , 2) +- MIPS_SYS(sys_nice , 1) +- MIPS_SYS(sys_ni_syscall , 0) /* 4035 */ +- MIPS_SYS(sys_sync , 0) +- MIPS_SYS(sys_kill , 2) +- MIPS_SYS(sys_rename , 2) +- MIPS_SYS(sys_mkdir , 2) +- MIPS_SYS(sys_rmdir , 1) /* 4040 */ +- MIPS_SYS(sys_dup , 1) +- MIPS_SYS(sys_pipe , 0) +- MIPS_SYS(sys_times , 1) +- MIPS_SYS(sys_ni_syscall , 0) +- MIPS_SYS(sys_brk , 1) /* 4045 */ +- MIPS_SYS(sys_setgid , 1) +- MIPS_SYS(sys_getgid , 0) +- MIPS_SYS(sys_ni_syscall , 0) /* was signal(2) */ +- MIPS_SYS(sys_geteuid , 0) +- MIPS_SYS(sys_getegid , 0) /* 4050 */ +- MIPS_SYS(sys_acct , 0) +- MIPS_SYS(sys_umount2 , 2) +- MIPS_SYS(sys_ni_syscall , 0) +- MIPS_SYS(sys_ioctl , 3) +- MIPS_SYS(sys_fcntl , 3) /* 4055 */ +- MIPS_SYS(sys_ni_syscall , 2) +- MIPS_SYS(sys_setpgid , 2) +- MIPS_SYS(sys_ni_syscall , 0) +- MIPS_SYS(sys_olduname , 1) +- MIPS_SYS(sys_umask , 1) /* 4060 */ +- MIPS_SYS(sys_chroot , 1) +- MIPS_SYS(sys_ustat , 2) +- MIPS_SYS(sys_dup2 , 2) +- MIPS_SYS(sys_getppid , 0) +- MIPS_SYS(sys_getpgrp , 0) /* 4065 */ +- MIPS_SYS(sys_setsid , 0) +- MIPS_SYS(sys_sigaction , 3) +- MIPS_SYS(sys_sgetmask , 0) +- MIPS_SYS(sys_ssetmask , 1) +- MIPS_SYS(sys_setreuid , 2) /* 4070 */ +- MIPS_SYS(sys_setregid , 2) +- MIPS_SYS(sys_sigsuspend , 0) +- MIPS_SYS(sys_sigpending , 1) +- MIPS_SYS(sys_sethostname , 2) +- MIPS_SYS(sys_setrlimit , 2) /* 4075 */ +- MIPS_SYS(sys_getrlimit , 2) +- MIPS_SYS(sys_getrusage , 2) +- MIPS_SYS(sys_gettimeofday, 2) +- MIPS_SYS(sys_settimeofday, 2) +- MIPS_SYS(sys_getgroups , 2) /* 4080 */ +- MIPS_SYS(sys_setgroups , 2) +- MIPS_SYS(sys_ni_syscall , 0) /* old_select */ +- MIPS_SYS(sys_symlink , 2) +- MIPS_SYS(sys_ni_syscall , 0) /* was sys_lstat */ +- MIPS_SYS(sys_readlink , 3) /* 4085 */ +- MIPS_SYS(sys_uselib , 1) +- MIPS_SYS(sys_swapon , 2) +- MIPS_SYS(sys_reboot , 3) +- MIPS_SYS(old_readdir , 3) +- MIPS_SYS(old_mmap , 6) /* 4090 */ +- MIPS_SYS(sys_munmap , 2) +- MIPS_SYS(sys_truncate , 2) +- MIPS_SYS(sys_ftruncate , 2) +- MIPS_SYS(sys_fchmod , 2) +- MIPS_SYS(sys_fchown , 3) /* 4095 */ +- MIPS_SYS(sys_getpriority , 2) +- MIPS_SYS(sys_setpriority , 3) +- MIPS_SYS(sys_ni_syscall , 0) +- MIPS_SYS(sys_statfs , 2) +- MIPS_SYS(sys_fstatfs , 2) /* 4100 */ +- MIPS_SYS(sys_ni_syscall , 0) /* was ioperm(2) */ +- MIPS_SYS(sys_socketcall , 2) +- MIPS_SYS(sys_syslog , 3) +- MIPS_SYS(sys_setitimer , 3) +- MIPS_SYS(sys_getitimer , 2) /* 4105 */ +- MIPS_SYS(sys_newstat , 2) +- MIPS_SYS(sys_newlstat , 2) +- MIPS_SYS(sys_newfstat , 2) +- MIPS_SYS(sys_uname , 1) +- MIPS_SYS(sys_ni_syscall , 0) /* 4110 was iopl(2) */ +- MIPS_SYS(sys_vhangup , 0) +- MIPS_SYS(sys_ni_syscall , 0) /* was sys_idle() */ +- MIPS_SYS(sys_ni_syscall , 0) /* was sys_vm86 */ +- MIPS_SYS(sys_wait4 , 4) +- MIPS_SYS(sys_swapoff , 1) /* 4115 */ +- MIPS_SYS(sys_sysinfo , 1) +- MIPS_SYS(sys_ipc , 6) +- MIPS_SYS(sys_fsync , 1) +- MIPS_SYS(sys_sigreturn , 0) +- MIPS_SYS(sys_clone , 6) /* 4120 */ +- MIPS_SYS(sys_setdomainname, 2) +- MIPS_SYS(sys_newuname , 1) +- MIPS_SYS(sys_ni_syscall , 0) /* sys_modify_ldt */ +- MIPS_SYS(sys_adjtimex , 1) +- MIPS_SYS(sys_mprotect , 3) /* 4125 */ +- MIPS_SYS(sys_sigprocmask , 3) +- MIPS_SYS(sys_ni_syscall , 0) /* was create_module */ +- MIPS_SYS(sys_init_module , 5) +- MIPS_SYS(sys_delete_module, 1) +- MIPS_SYS(sys_ni_syscall , 0) /* 4130 was get_kernel_syms */ +- MIPS_SYS(sys_quotactl , 0) +- MIPS_SYS(sys_getpgid , 1) +- MIPS_SYS(sys_fchdir , 1) +- MIPS_SYS(sys_bdflush , 2) +- MIPS_SYS(sys_sysfs , 3) /* 4135 */ +- MIPS_SYS(sys_personality , 1) +- MIPS_SYS(sys_ni_syscall , 0) /* for afs_syscall */ +- MIPS_SYS(sys_setfsuid , 1) +- MIPS_SYS(sys_setfsgid , 1) +- MIPS_SYS(sys_llseek , 5) /* 4140 */ +- MIPS_SYS(sys_getdents , 3) +- MIPS_SYS(sys_select , 5) +- MIPS_SYS(sys_flock , 2) +- MIPS_SYS(sys_msync , 3) +- MIPS_SYS(sys_readv , 3) /* 4145 */ +- MIPS_SYS(sys_writev , 3) +- MIPS_SYS(sys_cacheflush , 3) +- MIPS_SYS(sys_cachectl , 3) +- MIPS_SYS(sys_sysmips , 4) +- MIPS_SYS(sys_ni_syscall , 0) /* 4150 */ +- MIPS_SYS(sys_getsid , 1) +- MIPS_SYS(sys_fdatasync , 0) +- MIPS_SYS(sys_sysctl , 1) +- MIPS_SYS(sys_mlock , 2) +- MIPS_SYS(sys_munlock , 2) /* 4155 */ +- MIPS_SYS(sys_mlockall , 1) +- MIPS_SYS(sys_munlockall , 0) +- MIPS_SYS(sys_sched_setparam, 2) +- MIPS_SYS(sys_sched_getparam, 2) +- MIPS_SYS(sys_sched_setscheduler, 3) /* 4160 */ +- MIPS_SYS(sys_sched_getscheduler, 1) +- MIPS_SYS(sys_sched_yield , 0) +- MIPS_SYS(sys_sched_get_priority_max, 1) +- MIPS_SYS(sys_sched_get_priority_min, 1) +- MIPS_SYS(sys_sched_rr_get_interval, 2) /* 4165 */ +- MIPS_SYS(sys_nanosleep, 2) +- MIPS_SYS(sys_mremap , 5) +- MIPS_SYS(sys_accept , 3) +- MIPS_SYS(sys_bind , 3) +- MIPS_SYS(sys_connect , 3) /* 4170 */ +- MIPS_SYS(sys_getpeername , 3) +- MIPS_SYS(sys_getsockname , 3) +- MIPS_SYS(sys_getsockopt , 5) +- MIPS_SYS(sys_listen , 2) +- MIPS_SYS(sys_recv , 4) /* 4175 */ +- MIPS_SYS(sys_recvfrom , 6) +- MIPS_SYS(sys_recvmsg , 3) +- MIPS_SYS(sys_send , 4) +- MIPS_SYS(sys_sendmsg , 3) +- MIPS_SYS(sys_sendto , 6) /* 4180 */ +- MIPS_SYS(sys_setsockopt , 5) +- MIPS_SYS(sys_shutdown , 2) +- MIPS_SYS(sys_socket , 3) +- MIPS_SYS(sys_socketpair , 4) +- MIPS_SYS(sys_setresuid , 3) /* 4185 */ +- MIPS_SYS(sys_getresuid , 3) +- MIPS_SYS(sys_ni_syscall , 0) /* was sys_query_module */ +- MIPS_SYS(sys_poll , 3) +- MIPS_SYS(sys_nfsservctl , 3) +- MIPS_SYS(sys_setresgid , 3) /* 4190 */ +- MIPS_SYS(sys_getresgid , 3) +- MIPS_SYS(sys_prctl , 5) +- MIPS_SYS(sys_rt_sigreturn, 0) +- MIPS_SYS(sys_rt_sigaction, 4) +- MIPS_SYS(sys_rt_sigprocmask, 4) /* 4195 */ +- MIPS_SYS(sys_rt_sigpending, 2) +- MIPS_SYS(sys_rt_sigtimedwait, 4) +- MIPS_SYS(sys_rt_sigqueueinfo, 3) +- MIPS_SYS(sys_rt_sigsuspend, 0) +- MIPS_SYS(sys_pread64 , 6) /* 4200 */ +- MIPS_SYS(sys_pwrite64 , 6) +- MIPS_SYS(sys_chown , 3) +- MIPS_SYS(sys_getcwd , 2) +- MIPS_SYS(sys_capget , 2) +- MIPS_SYS(sys_capset , 2) /* 4205 */ +- MIPS_SYS(sys_sigaltstack , 2) +- MIPS_SYS(sys_sendfile , 4) +- MIPS_SYS(sys_ni_syscall , 0) +- MIPS_SYS(sys_ni_syscall , 0) +- MIPS_SYS(sys_mmap2 , 6) /* 4210 */ +- MIPS_SYS(sys_truncate64 , 4) +- MIPS_SYS(sys_ftruncate64 , 4) +- MIPS_SYS(sys_stat64 , 2) +- MIPS_SYS(sys_lstat64 , 2) +- MIPS_SYS(sys_fstat64 , 2) /* 4215 */ +- MIPS_SYS(sys_pivot_root , 2) +- MIPS_SYS(sys_mincore , 3) +- MIPS_SYS(sys_madvise , 3) +- MIPS_SYS(sys_getdents64 , 3) +- MIPS_SYS(sys_fcntl64 , 3) /* 4220 */ +- MIPS_SYS(sys_ni_syscall , 0) +- MIPS_SYS(sys_gettid , 0) +- MIPS_SYS(sys_readahead , 5) +- MIPS_SYS(sys_setxattr , 5) +- MIPS_SYS(sys_lsetxattr , 5) /* 4225 */ +- MIPS_SYS(sys_fsetxattr , 5) +- MIPS_SYS(sys_getxattr , 4) +- MIPS_SYS(sys_lgetxattr , 4) +- MIPS_SYS(sys_fgetxattr , 4) +- MIPS_SYS(sys_listxattr , 3) /* 4230 */ +- MIPS_SYS(sys_llistxattr , 3) +- MIPS_SYS(sys_flistxattr , 3) +- MIPS_SYS(sys_removexattr , 2) +- MIPS_SYS(sys_lremovexattr, 2) +- MIPS_SYS(sys_fremovexattr, 2) /* 4235 */ +- MIPS_SYS(sys_tkill , 2) +- MIPS_SYS(sys_sendfile64 , 5) +- MIPS_SYS(sys_futex , 6) +- MIPS_SYS(sys_sched_setaffinity, 3) +- MIPS_SYS(sys_sched_getaffinity, 3) /* 4240 */ +- MIPS_SYS(sys_io_setup , 2) +- MIPS_SYS(sys_io_destroy , 1) +- MIPS_SYS(sys_io_getevents, 5) +- MIPS_SYS(sys_io_submit , 3) +- MIPS_SYS(sys_io_cancel , 3) /* 4245 */ +- MIPS_SYS(sys_exit_group , 1) +- MIPS_SYS(sys_lookup_dcookie, 3) +- MIPS_SYS(sys_epoll_create, 1) +- MIPS_SYS(sys_epoll_ctl , 4) +- MIPS_SYS(sys_epoll_wait , 3) /* 4250 */ +- MIPS_SYS(sys_remap_file_pages, 5) +- MIPS_SYS(sys_set_tid_address, 1) +- MIPS_SYS(sys_restart_syscall, 0) +- MIPS_SYS(sys_fadvise64_64, 7) +- MIPS_SYS(sys_statfs64 , 3) /* 4255 */ +- MIPS_SYS(sys_fstatfs64 , 2) +- MIPS_SYS(sys_timer_create, 3) +- MIPS_SYS(sys_timer_settime, 4) +- MIPS_SYS(sys_timer_gettime, 2) +- MIPS_SYS(sys_timer_getoverrun, 1) /* 4260 */ +- MIPS_SYS(sys_timer_delete, 1) +- MIPS_SYS(sys_clock_settime, 2) +- MIPS_SYS(sys_clock_gettime, 2) +- MIPS_SYS(sys_clock_getres, 2) +- MIPS_SYS(sys_clock_nanosleep, 4) /* 4265 */ +- MIPS_SYS(sys_tgkill , 3) +- MIPS_SYS(sys_utimes , 2) +- MIPS_SYS(sys_mbind , 4) +- MIPS_SYS(sys_ni_syscall , 0) /* sys_get_mempolicy */ +- MIPS_SYS(sys_ni_syscall , 0) /* 4270 sys_set_mempolicy */ +- MIPS_SYS(sys_mq_open , 4) +- MIPS_SYS(sys_mq_unlink , 1) +- MIPS_SYS(sys_mq_timedsend, 5) +- MIPS_SYS(sys_mq_timedreceive, 5) +- MIPS_SYS(sys_mq_notify , 2) /* 4275 */ +- MIPS_SYS(sys_mq_getsetattr, 3) +- MIPS_SYS(sys_ni_syscall , 0) /* sys_vserver */ +- MIPS_SYS(sys_waitid , 4) +- MIPS_SYS(sys_ni_syscall , 0) /* available, was setaltroot */ +- MIPS_SYS(sys_add_key , 5) +- MIPS_SYS(sys_request_key, 4) +- MIPS_SYS(sys_keyctl , 5) +- MIPS_SYS(sys_set_thread_area, 1) +- MIPS_SYS(sys_inotify_init, 0) +- MIPS_SYS(sys_inotify_add_watch, 3) /* 4285 */ +- MIPS_SYS(sys_inotify_rm_watch, 2) +- MIPS_SYS(sys_migrate_pages, 4) +- MIPS_SYS(sys_openat, 4) +- MIPS_SYS(sys_mkdirat, 3) +- MIPS_SYS(sys_mknodat, 4) /* 4290 */ +- MIPS_SYS(sys_fchownat, 5) +- MIPS_SYS(sys_futimesat, 3) +- MIPS_SYS(sys_fstatat64, 4) +- MIPS_SYS(sys_unlinkat, 3) +- MIPS_SYS(sys_renameat, 4) /* 4295 */ +- MIPS_SYS(sys_linkat, 5) +- MIPS_SYS(sys_symlinkat, 3) +- MIPS_SYS(sys_readlinkat, 4) +- MIPS_SYS(sys_fchmodat, 3) +- MIPS_SYS(sys_faccessat, 3) /* 4300 */ +- MIPS_SYS(sys_pselect6, 6) +- MIPS_SYS(sys_ppoll, 5) +- MIPS_SYS(sys_unshare, 1) +- MIPS_SYS(sys_splice, 6) +- MIPS_SYS(sys_sync_file_range, 7) /* 4305 */ +- MIPS_SYS(sys_tee, 4) +- MIPS_SYS(sys_vmsplice, 4) +- MIPS_SYS(sys_move_pages, 6) +- MIPS_SYS(sys_set_robust_list, 2) +- MIPS_SYS(sys_get_robust_list, 3) /* 4310 */ +- MIPS_SYS(sys_kexec_load, 4) +- MIPS_SYS(sys_getcpu, 3) +- MIPS_SYS(sys_epoll_pwait, 6) +- MIPS_SYS(sys_ioprio_set, 3) +- MIPS_SYS(sys_ioprio_get, 2) +- MIPS_SYS(sys_utimensat, 4) +- MIPS_SYS(sys_signalfd, 3) +- MIPS_SYS(sys_ni_syscall, 0) /* was timerfd */ +- MIPS_SYS(sys_eventfd, 1) +- MIPS_SYS(sys_fallocate, 6) /* 4320 */ +- MIPS_SYS(sys_timerfd_create, 2) +- MIPS_SYS(sys_timerfd_gettime, 2) +- MIPS_SYS(sys_timerfd_settime, 4) +- MIPS_SYS(sys_signalfd4, 4) +- MIPS_SYS(sys_eventfd2, 2) /* 4325 */ +- MIPS_SYS(sys_epoll_create1, 1) +- MIPS_SYS(sys_dup3, 3) +- MIPS_SYS(sys_pipe2, 2) +- MIPS_SYS(sys_inotify_init1, 1) +- MIPS_SYS(sys_preadv, 6) /* 4330 */ +- MIPS_SYS(sys_pwritev, 6) +- MIPS_SYS(sys_rt_tgsigqueueinfo, 4) +- MIPS_SYS(sys_perf_event_open, 5) +- MIPS_SYS(sys_accept4, 4) +- MIPS_SYS(sys_recvmmsg, 5) /* 4335 */ +- MIPS_SYS(sys_fanotify_init, 2) +- MIPS_SYS(sys_fanotify_mark, 6) +- MIPS_SYS(sys_prlimit64, 4) +- MIPS_SYS(sys_name_to_handle_at, 5) +- MIPS_SYS(sys_open_by_handle_at, 3) /* 4340 */ +- MIPS_SYS(sys_clock_adjtime, 2) +- MIPS_SYS(sys_syncfs, 1) +-}; +-# undef MIPS_SYS +-# endif /* O32 */ +- +-static int do_store_exclusive(CPUMIPSState *env) +-{ +- target_ulong addr; +- target_ulong page_addr; +- target_ulong val; +- int flags; +- int segv = 0; +- int reg; +- int d; +- +- addr = env->lladdr; +- page_addr = addr & TARGET_PAGE_MASK; +- start_exclusive(); +- mmap_lock(); +- flags = page_get_flags(page_addr); +- if ((flags & PAGE_READ) == 0) { +- segv = 1; +- } else { +- reg = env->llreg & 0x1f; +- d = (env->llreg & 0x20) != 0; +- if (d) { +- segv = get_user_s64(val, addr); +- } else { +- segv = get_user_s32(val, addr); +- } +- if (!segv) { +- if (val != env->llval) { +- env->active_tc.gpr[reg] = 0; +- } else { +- if (d) { +- segv = put_user_u64(env->llnewval, addr); +- } else { +- segv = put_user_u32(env->llnewval, addr); +- } +- if (!segv) { +- env->active_tc.gpr[reg] = 1; +- } +- } +- } +- } +- env->lladdr = -1; +- if (!segv) { +- env->active_tc.PC += 4; +- } +- mmap_unlock(); +- end_exclusive(); +- return segv; +-} +- +-/* Break codes */ +-enum { +- BRK_OVERFLOW = 6, +- BRK_DIVZERO = 7 +-}; +- +-static int do_break(CPUMIPSState *env, target_siginfo_t *info, +- unsigned int code) +-{ +- int ret = -1; +- +- switch (code) { +- case BRK_OVERFLOW: +- case BRK_DIVZERO: +- info->si_signo = TARGET_SIGFPE; +- info->si_errno = 0; +- info->si_code = (code == BRK_OVERFLOW) ? FPE_INTOVF : FPE_INTDIV; +- queue_signal(env, info->si_signo, &*info); +- ret = 0; +- break; +- default: +- info->si_signo = TARGET_SIGTRAP; +- info->si_errno = 0; +- queue_signal(env, info->si_signo, &*info); +- ret = 0; +- break; +- } +- +- return ret; +-} +- +-void cpu_loop(CPUMIPSState *env) +-{ +- CPUState *cs = CPU(mips_env_get_cpu(env)); +- target_siginfo_t info; +- int trapnr; +- abi_long ret; +-# ifdef TARGET_ABI_MIPSO32 +- unsigned int syscall_num; +-# endif +- +- for(;;) { +- cpu_exec_start(cs); +- trapnr = cpu_mips_exec(env); +- cpu_exec_end(cs); +- switch(trapnr) { +- case EXCP_SYSCALL: +- env->active_tc.PC += 4; +-# ifdef TARGET_ABI_MIPSO32 +- syscall_num = env->active_tc.gpr[2] - 4000; +- if (syscall_num >= sizeof(mips_syscall_args)) { +- ret = -TARGET_ENOSYS; +- } else { +- int nb_args; +- abi_ulong sp_reg; +- abi_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0; +- +- nb_args = mips_syscall_args[syscall_num]; +- sp_reg = env->active_tc.gpr[29]; +- switch (nb_args) { +- /* these arguments are taken from the stack */ +- case 8: +- if ((ret = get_user_ual(arg8, sp_reg + 28)) != 0) { +- goto done_syscall; +- } +- case 7: +- if ((ret = get_user_ual(arg7, sp_reg + 24)) != 0) { +- goto done_syscall; +- } +- case 6: +- if ((ret = get_user_ual(arg6, sp_reg + 20)) != 0) { +- goto done_syscall; +- } +- case 5: +- if ((ret = get_user_ual(arg5, sp_reg + 16)) != 0) { +- goto done_syscall; +- } +- default: +- break; +- } +- ret = do_syscall(env, env->active_tc.gpr[2], +- env->active_tc.gpr[4], +- env->active_tc.gpr[5], +- env->active_tc.gpr[6], +- env->active_tc.gpr[7], +- arg5, arg6, arg7, arg8); +- } +-done_syscall: +-# else +- ret = do_syscall(env, env->active_tc.gpr[2], +- env->active_tc.gpr[4], env->active_tc.gpr[5], +- env->active_tc.gpr[6], env->active_tc.gpr[7], +- env->active_tc.gpr[8], env->active_tc.gpr[9], +- env->active_tc.gpr[10], env->active_tc.gpr[11]); +-# endif /* O32 */ +- if (ret == -TARGET_QEMU_ESIGRETURN) { +- /* Returning from a successful sigreturn syscall. +- Avoid clobbering register state. */ +- break; +- } +- if ((abi_ulong)ret >= (abi_ulong)-1133) { +- env->active_tc.gpr[7] = 1; /* error flag */ +- ret = -ret; +- } else { +- env->active_tc.gpr[7] = 0; /* error flag */ +- } +- env->active_tc.gpr[2] = ret; +- break; +- case EXCP_TLBL: +- case EXCP_TLBS: +- case EXCP_AdEL: +- case EXCP_AdES: +- info.si_signo = TARGET_SIGSEGV; +- info.si_errno = 0; +- /* XXX: check env->error_code */ +- info.si_code = TARGET_SEGV_MAPERR; +- info._sifields._sigfault._addr = env->CP0_BadVAddr; +- queue_signal(env, info.si_signo, &info); +- break; +- case EXCP_CpU: +- case EXCP_RI: +- info.si_signo = TARGET_SIGILL; +- info.si_errno = 0; +- info.si_code = 0; +- queue_signal(env, info.si_signo, &info); +- break; +- case EXCP_INTERRUPT: +- /* just indicate that signals should be handled asap */ +- break; +- case EXCP_DEBUG: +- { +- int sig; +- +- sig = gdb_handlesig(cs, TARGET_SIGTRAP); +- if (sig) +- { +- info.si_signo = sig; +- info.si_errno = 0; +- info.si_code = TARGET_TRAP_BRKPT; +- queue_signal(env, info.si_signo, &info); +- } +- } +- break; +- case EXCP_SC: +- if (do_store_exclusive(env)) { +- info.si_signo = TARGET_SIGSEGV; +- info.si_errno = 0; +- info.si_code = TARGET_SEGV_MAPERR; +- info._sifields._sigfault._addr = env->active_tc.PC; +- queue_signal(env, info.si_signo, &info); +- } +- break; +- case EXCP_DSPDIS: +- info.si_signo = TARGET_SIGILL; +- info.si_errno = 0; +- info.si_code = TARGET_ILL_ILLOPC; +- queue_signal(env, info.si_signo, &info); +- break; +- /* The code below was inspired by the MIPS Linux kernel trap +- * handling code in arch/mips/kernel/traps.c. +- */ +- case EXCP_BREAK: +- { +- abi_ulong trap_instr; +- unsigned int code; +- +- if (env->hflags & MIPS_HFLAG_M16) { +- if (env->insn_flags & ASE_MICROMIPS) { +- /* microMIPS mode */ +- ret = get_user_u16(trap_instr, env->active_tc.PC); +- if (ret != 0) { +- goto error; +- } +- +- if ((trap_instr >> 10) == 0x11) { +- /* 16-bit instruction */ +- code = trap_instr & 0xf; +- } else { +- /* 32-bit instruction */ +- abi_ulong instr_lo; +- +- ret = get_user_u16(instr_lo, +- env->active_tc.PC + 2); +- if (ret != 0) { +- goto error; +- } +- trap_instr = (trap_instr << 16) | instr_lo; +- code = ((trap_instr >> 6) & ((1 << 20) - 1)); +- /* Unfortunately, microMIPS also suffers from +- the old assembler bug... */ +- if (code >= (1 << 10)) { +- code >>= 10; +- } +- } +- } else { +- /* MIPS16e mode */ +- ret = get_user_u16(trap_instr, env->active_tc.PC); +- if (ret != 0) { +- goto error; +- } +- code = (trap_instr >> 6) & 0x3f; +- } +- } else { +- ret = get_user_ual(trap_instr, env->active_tc.PC); +- if (ret != 0) { +- goto error; +- } +- +- /* As described in the original Linux kernel code, the +- * below checks on 'code' are to work around an old +- * assembly bug. +- */ +- code = ((trap_instr >> 6) & ((1 << 20) - 1)); +- if (code >= (1 << 10)) { +- code >>= 10; +- } +- } +- +- if (do_break(env, &info, code) != 0) { +- goto error; +- } +- } +- break; +- case EXCP_TRAP: +- { +- abi_ulong trap_instr; +- unsigned int code = 0; +- +- if (env->hflags & MIPS_HFLAG_M16) { +- /* microMIPS mode */ +- abi_ulong instr[2]; +- +- ret = get_user_u16(instr[0], env->active_tc.PC) || +- get_user_u16(instr[1], env->active_tc.PC + 2); +- +- trap_instr = (instr[0] << 16) | instr[1]; +- } else { +- ret = get_user_ual(trap_instr, env->active_tc.PC); +- } +- +- if (ret != 0) { +- goto error; +- } +- +- /* The immediate versions don't provide a code. */ +- if (!(trap_instr & 0xFC000000)) { +- if (env->hflags & MIPS_HFLAG_M16) { +- /* microMIPS mode */ +- code = ((trap_instr >> 12) & ((1 << 4) - 1)); +- } else { +- code = ((trap_instr >> 6) & ((1 << 10) - 1)); +- } +- } +- +- if (do_break(env, &info, code) != 0) { +- goto error; +- } +- } +- break; +- default: +-error: +- fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", +- trapnr); +- cpu_dump_state(cs, stderr, fprintf, 0); +- abort(); +- } +- process_pending_signals(env); +- } +-} +-#endif +- +-#ifdef TARGET_OPENRISC +- +-void cpu_loop(CPUOpenRISCState *env) +-{ +- CPUState *cs = CPU(openrisc_env_get_cpu(env)); +- int trapnr, gdbsig; +- +- for (;;) { +- cpu_exec_start(cs); +- trapnr = cpu_exec(env); +- cpu_exec_end(cs); +- gdbsig = 0; +- +- switch (trapnr) { +- case EXCP_RESET: +- qemu_log("\nReset request, exit, pc is %#x\n", env->pc); +- exit(1); +- break; +- case EXCP_BUSERR: +- qemu_log("\nBus error, exit, pc is %#x\n", env->pc); +- gdbsig = TARGET_SIGBUS; +- break; +- case EXCP_DPF: +- case EXCP_IPF: +- cpu_dump_state(cs, stderr, fprintf, 0); +- gdbsig = TARGET_SIGSEGV; +- break; +- case EXCP_TICK: +- qemu_log("\nTick time interrupt pc is %#x\n", env->pc); +- break; +- case EXCP_ALIGN: +- qemu_log("\nAlignment pc is %#x\n", env->pc); +- gdbsig = TARGET_SIGBUS; +- break; +- case EXCP_ILLEGAL: +- qemu_log("\nIllegal instructionpc is %#x\n", env->pc); +- gdbsig = TARGET_SIGILL; +- break; +- case EXCP_INT: +- qemu_log("\nExternal interruptpc is %#x\n", env->pc); +- break; +- case EXCP_DTLBMISS: +- case EXCP_ITLBMISS: +- qemu_log("\nTLB miss\n"); +- break; +- case EXCP_RANGE: +- qemu_log("\nRange\n"); +- gdbsig = TARGET_SIGSEGV; +- break; +- case EXCP_SYSCALL: +- env->pc += 4; /* 0xc00; */ +- env->gpr[11] = do_syscall(env, +- env->gpr[11], /* return value */ +- env->gpr[3], /* r3 - r7 are params */ +- env->gpr[4], +- env->gpr[5], +- env->gpr[6], +- env->gpr[7], +- env->gpr[8], 0, 0); +- break; +- case EXCP_FPE: +- qemu_log("\nFloating point error\n"); +- break; +- case EXCP_TRAP: +- qemu_log("\nTrap\n"); +- gdbsig = TARGET_SIGTRAP; +- break; +- case EXCP_NR: +- qemu_log("\nNR\n"); +- break; +- default: +- qemu_log("\nqemu: unhandled CPU exception %#x - aborting\n", +- trapnr); +- cpu_dump_state(cs, stderr, fprintf, 0); +- gdbsig = TARGET_SIGILL; +- break; +- } +- if (gdbsig) { +- gdb_handlesig(cs, gdbsig); +- if (gdbsig != TARGET_SIGTRAP) { +- exit(1); +- } +- } +- +- process_pending_signals(env); +- } +-} +- +-#endif /* TARGET_OPENRISC */ +- +-#ifdef TARGET_SH4 +-void cpu_loop(CPUSH4State *env) +-{ +- CPUState *cs = CPU(sh_env_get_cpu(env)); +- int trapnr, ret; +- target_siginfo_t info; +- +- while (1) { +- cpu_exec_start(cs); +- trapnr = cpu_sh4_exec (env); +- cpu_exec_end(cs); +- +- switch (trapnr) { +- case 0x160: +- env->pc += 2; +- ret = do_syscall(env, +- env->gregs[3], +- env->gregs[4], +- env->gregs[5], +- env->gregs[6], +- env->gregs[7], +- env->gregs[0], +- env->gregs[1], +- 0, 0); +- env->gregs[0] = ret; +- break; +- case EXCP_INTERRUPT: +- /* just indicate that signals should be handled asap */ +- break; +- case EXCP_DEBUG: +- { +- int sig; +- +- sig = gdb_handlesig(cs, TARGET_SIGTRAP); +- if (sig) +- { +- info.si_signo = sig; +- info.si_errno = 0; +- info.si_code = TARGET_TRAP_BRKPT; +- queue_signal(env, info.si_signo, &info); +- } +- } +- break; +- case 0xa0: +- case 0xc0: +- info.si_signo = TARGET_SIGSEGV; +- info.si_errno = 0; +- info.si_code = TARGET_SEGV_MAPERR; +- info._sifields._sigfault._addr = env->tea; +- queue_signal(env, info.si_signo, &info); +- break; +- +- default: +- printf ("Unhandled trap: 0x%x\n", trapnr); +- cpu_dump_state(cs, stderr, fprintf, 0); +- exit (1); +- } +- process_pending_signals (env); +- } +-} +-#endif +- +-#ifdef TARGET_CRIS +-void cpu_loop(CPUCRISState *env) +-{ +- CPUState *cs = CPU(cris_env_get_cpu(env)); +- int trapnr, ret; +- target_siginfo_t info; +- +- while (1) { +- cpu_exec_start(cs); +- trapnr = cpu_cris_exec (env); +- cpu_exec_end(cs); +- switch (trapnr) { +- case 0xaa: +- { +- info.si_signo = TARGET_SIGSEGV; +- info.si_errno = 0; +- /* XXX: check env->error_code */ +- info.si_code = TARGET_SEGV_MAPERR; +- info._sifields._sigfault._addr = env->pregs[PR_EDA]; +- queue_signal(env, info.si_signo, &info); +- } +- break; +- case EXCP_INTERRUPT: +- /* just indicate that signals should be handled asap */ +- break; +- case EXCP_BREAK: +- ret = do_syscall(env, +- env->regs[9], +- env->regs[10], +- env->regs[11], +- env->regs[12], +- env->regs[13], +- env->pregs[7], +- env->pregs[11], +- 0, 0); +- env->regs[10] = ret; +- break; +- case EXCP_DEBUG: +- { +- int sig; +- +- sig = gdb_handlesig(cs, TARGET_SIGTRAP); +- if (sig) +- { +- info.si_signo = sig; +- info.si_errno = 0; +- info.si_code = TARGET_TRAP_BRKPT; +- queue_signal(env, info.si_signo, &info); +- } +- } +- break; +- default: +- printf ("Unhandled trap: 0x%x\n", trapnr); +- cpu_dump_state(cs, stderr, fprintf, 0); +- exit (1); +- } +- process_pending_signals (env); +- } +-} +-#endif +- +-#ifdef TARGET_MICROBLAZE +-void cpu_loop(CPUMBState *env) +-{ +- CPUState *cs = CPU(mb_env_get_cpu(env)); +- int trapnr, ret; +- target_siginfo_t info; +- +- while (1) { +- cpu_exec_start(cs); +- trapnr = cpu_mb_exec (env); +- cpu_exec_end(cs); +- switch (trapnr) { +- case 0xaa: +- { +- info.si_signo = TARGET_SIGSEGV; +- info.si_errno = 0; +- /* XXX: check env->error_code */ +- info.si_code = TARGET_SEGV_MAPERR; +- info._sifields._sigfault._addr = 0; +- queue_signal(env, info.si_signo, &info); +- } +- break; +- case EXCP_INTERRUPT: +- /* just indicate that signals should be handled asap */ +- break; +- case EXCP_BREAK: +- /* Return address is 4 bytes after the call. */ +- env->regs[14] += 4; +- env->sregs[SR_PC] = env->regs[14]; +- ret = do_syscall(env, +- env->regs[12], +- env->regs[5], +- env->regs[6], +- env->regs[7], +- env->regs[8], +- env->regs[9], +- env->regs[10], +- 0, 0); +- env->regs[3] = ret; +- break; +- case EXCP_HW_EXCP: +- env->regs[17] = env->sregs[SR_PC] + 4; +- if (env->iflags & D_FLAG) { +- env->sregs[SR_ESR] |= 1 << 12; +- env->sregs[SR_PC] -= 4; +- /* FIXME: if branch was immed, replay the imm as well. */ +- } +- +- env->iflags &= ~(IMM_FLAG | D_FLAG); +- +- switch (env->sregs[SR_ESR] & 31) { +- case ESR_EC_DIVZERO: +- info.si_signo = TARGET_SIGFPE; +- info.si_errno = 0; +- info.si_code = TARGET_FPE_FLTDIV; +- info._sifields._sigfault._addr = 0; +- queue_signal(env, info.si_signo, &info); +- break; +- case ESR_EC_FPU: +- info.si_signo = TARGET_SIGFPE; +- info.si_errno = 0; +- if (env->sregs[SR_FSR] & FSR_IO) { +- info.si_code = TARGET_FPE_FLTINV; +- } +- if (env->sregs[SR_FSR] & FSR_DZ) { +- info.si_code = TARGET_FPE_FLTDIV; +- } +- info._sifields._sigfault._addr = 0; +- queue_signal(env, info.si_signo, &info); +- break; +- default: +- printf ("Unhandled hw-exception: 0x%x\n", +- env->sregs[SR_ESR] & ESR_EC_MASK); +- cpu_dump_state(cs, stderr, fprintf, 0); +- exit (1); +- break; +- } +- break; +- case EXCP_DEBUG: +- { +- int sig; +- +- sig = gdb_handlesig(cs, TARGET_SIGTRAP); +- if (sig) +- { +- info.si_signo = sig; +- info.si_errno = 0; +- info.si_code = TARGET_TRAP_BRKPT; +- queue_signal(env, info.si_signo, &info); +- } +- } +- break; +- default: +- printf ("Unhandled trap: 0x%x\n", trapnr); +- cpu_dump_state(cs, stderr, fprintf, 0); +- exit (1); +- } +- process_pending_signals (env); +- } +-} +-#endif +- +-#ifdef TARGET_M68K +- +-void cpu_loop(CPUM68KState *env) +-{ +- CPUState *cs = CPU(m68k_env_get_cpu(env)); +- int trapnr; +- unsigned int n; +- target_siginfo_t info; +- TaskState *ts = cs->opaque; +- +- for(;;) { +- cpu_exec_start(cs); +- trapnr = cpu_m68k_exec(env); +- cpu_exec_end(cs); +- switch(trapnr) { +- case EXCP_ILLEGAL: +- { +- if (ts->sim_syscalls) { +- uint16_t nr; +- get_user_u16(nr, env->pc + 2); +- env->pc += 4; +- do_m68k_simcall(env, nr); +- } else { +- goto do_sigill; +- } +- } +- break; +- case EXCP_HALT_INSN: +- /* Semihosing syscall. */ +- env->pc += 4; +- do_m68k_semihosting(env, env->dregs[0]); +- break; +- case EXCP_LINEA: +- case EXCP_LINEF: +- case EXCP_UNSUPPORTED: +- do_sigill: +- info.si_signo = TARGET_SIGILL; +- info.si_errno = 0; +- info.si_code = TARGET_ILL_ILLOPN; +- info._sifields._sigfault._addr = env->pc; +- queue_signal(env, info.si_signo, &info); +- break; +- case EXCP_TRAP0: +- { +- ts->sim_syscalls = 0; +- n = env->dregs[0]; +- env->pc += 2; +- env->dregs[0] = do_syscall(env, +- n, +- env->dregs[1], +- env->dregs[2], +- env->dregs[3], +- env->dregs[4], +- env->dregs[5], +- env->aregs[0], +- 0, 0); +- } +- break; +- case EXCP_INTERRUPT: +- /* just indicate that signals should be handled asap */ +- break; +- case EXCP_ACCESS: +- { +- info.si_signo = TARGET_SIGSEGV; +- info.si_errno = 0; +- /* XXX: check env->error_code */ +- info.si_code = TARGET_SEGV_MAPERR; +- info._sifields._sigfault._addr = env->mmu.ar; +- queue_signal(env, info.si_signo, &info); +- } +- break; +- case EXCP_DEBUG: +- { +- int sig; +- +- sig = gdb_handlesig(cs, TARGET_SIGTRAP); +- if (sig) +- { +- info.si_signo = sig; +- info.si_errno = 0; +- info.si_code = TARGET_TRAP_BRKPT; +- queue_signal(env, info.si_signo, &info); +- } +- } +- break; +- default: +- fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", +- trapnr); +- cpu_dump_state(cs, stderr, fprintf, 0); +- abort(); +- } +- process_pending_signals(env); +- } +-} +-#endif /* TARGET_M68K */ +- +-#ifdef TARGET_ALPHA +-static void do_store_exclusive(CPUAlphaState *env, int reg, int quad) +-{ +- target_ulong addr, val, tmp; +- target_siginfo_t info; +- int ret = 0; +- +- addr = env->lock_addr; +- tmp = env->lock_st_addr; +- env->lock_addr = -1; +- env->lock_st_addr = 0; +- +- start_exclusive(); +- mmap_lock(); +- +- if (addr == tmp) { +- if (quad ? get_user_s64(val, addr) : get_user_s32(val, addr)) { +- goto do_sigsegv; +- } +- +- if (val == env->lock_value) { +- tmp = env->ir[reg]; +- if (quad ? put_user_u64(tmp, addr) : put_user_u32(tmp, addr)) { +- goto do_sigsegv; +- } +- ret = 1; +- } +- } +- env->ir[reg] = ret; +- env->pc += 4; +- +- mmap_unlock(); +- end_exclusive(); +- return; +- +- do_sigsegv: +- mmap_unlock(); +- end_exclusive(); +- +- info.si_signo = TARGET_SIGSEGV; +- info.si_errno = 0; +- info.si_code = TARGET_SEGV_MAPERR; +- info._sifields._sigfault._addr = addr; +- queue_signal(env, TARGET_SIGSEGV, &info); +-} +- +-void cpu_loop(CPUAlphaState *env) +-{ +- CPUState *cs = CPU(alpha_env_get_cpu(env)); +- int trapnr; +- target_siginfo_t info; +- abi_long sysret; +- +- while (1) { +- cpu_exec_start(cs); +- trapnr = cpu_alpha_exec (env); +- cpu_exec_end(cs); +- +- /* All of the traps imply a transition through PALcode, which +- implies an REI instruction has been executed. Which means +- that the intr_flag should be cleared. */ +- env->intr_flag = 0; +- +- switch (trapnr) { +- case EXCP_RESET: +- fprintf(stderr, "Reset requested. Exit\n"); +- exit(1); +- break; +- case EXCP_MCHK: +- fprintf(stderr, "Machine check exception. Exit\n"); +- exit(1); +- break; +- case EXCP_SMP_INTERRUPT: +- case EXCP_CLK_INTERRUPT: +- case EXCP_DEV_INTERRUPT: +- fprintf(stderr, "External interrupt. Exit\n"); +- exit(1); +- break; +- case EXCP_MMFAULT: +- env->lock_addr = -1; +- info.si_signo = TARGET_SIGSEGV; +- info.si_errno = 0; +- info.si_code = (page_get_flags(env->trap_arg0) & PAGE_VALID +- ? TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR); +- info._sifields._sigfault._addr = env->trap_arg0; +- queue_signal(env, info.si_signo, &info); +- break; +- case EXCP_UNALIGN: +- env->lock_addr = -1; +- info.si_signo = TARGET_SIGBUS; +- info.si_errno = 0; +- info.si_code = TARGET_BUS_ADRALN; +- info._sifields._sigfault._addr = env->trap_arg0; +- queue_signal(env, info.si_signo, &info); +- break; +- case EXCP_OPCDEC: +- do_sigill: +- env->lock_addr = -1; +- info.si_signo = TARGET_SIGILL; +- info.si_errno = 0; +- info.si_code = TARGET_ILL_ILLOPC; +- info._sifields._sigfault._addr = env->pc; +- queue_signal(env, info.si_signo, &info); +- break; +- case EXCP_ARITH: +- env->lock_addr = -1; +- info.si_signo = TARGET_SIGFPE; +- info.si_errno = 0; +- info.si_code = TARGET_FPE_FLTINV; +- info._sifields._sigfault._addr = env->pc; +- queue_signal(env, info.si_signo, &info); +- break; +- case EXCP_FEN: +- /* No-op. Linux simply re-enables the FPU. */ +- break; +- case EXCP_CALL_PAL: +- env->lock_addr = -1; +- switch (env->error_code) { +- case 0x80: +- /* BPT */ +- info.si_signo = TARGET_SIGTRAP; +- info.si_errno = 0; +- info.si_code = TARGET_TRAP_BRKPT; +- info._sifields._sigfault._addr = env->pc; ++ info.si_code = TARGET_FPE_INTDIV; ++ info._sifields._sigfault._addr = env->eip; + queue_signal(env, info.si_signo, &info); +- break; +- case 0x81: +- /* BUGCHK */ ++ } ++ break; ++ case EXCP01_DB: ++ case EXCP03_INT3: ++ assert (!(env->eflags & VM_MASK)); /* Not _that_ old :) */ ++ { + info.si_signo = TARGET_SIGTRAP; + info.si_errno = 0; +- info.si_code = 0; +- info._sifields._sigfault._addr = env->pc; +- queue_signal(env, info.si_signo, &info); +- break; +- case 0x83: +- /* CALLSYS */ +- trapnr = env->ir[IR_V0]; +- sysret = do_syscall(env, trapnr, +- env->ir[IR_A0], env->ir[IR_A1], +- env->ir[IR_A2], env->ir[IR_A3], +- env->ir[IR_A4], env->ir[IR_A5], +- 0, 0); +- if (trapnr == TARGET_NR_sigreturn +- || trapnr == TARGET_NR_rt_sigreturn) { +- break; +- } +- /* Syscall writes 0 to V0 to bypass error check, similar +- to how this is handled internal to Linux kernel. +- (Ab)use trapnr temporarily as boolean indicating error. */ +- trapnr = (env->ir[IR_V0] != 0 && sysret < 0); +- env->ir[IR_V0] = (trapnr ? -sysret : sysret); +- env->ir[IR_A3] = trapnr; +- break; +- case 0x86: +- /* IMB */ +- /* ??? We can probably elide the code using page_unprotect +- that is checking for self-modifying code. Instead we +- could simply call tb_flush here. Until we work out the +- changes required to turn off the extra write protection, +- this can be a no-op. */ +- break; +- case 0x9E: +- /* RDUNIQUE */ +- /* Handled in the translator for usermode. */ +- abort(); +- case 0x9F: +- /* WRUNIQUE */ +- /* Handled in the translator for usermode. */ +- abort(); +- case 0xAA: +- /* GENTRAP */ +- info.si_signo = TARGET_SIGFPE; +- switch (env->ir[IR_A0]) { +- case TARGET_GEN_INTOVF: +- info.si_code = TARGET_FPE_INTOVF; +- break; +- case TARGET_GEN_INTDIV: +- info.si_code = TARGET_FPE_INTDIV; +- break; +- case TARGET_GEN_FLTOVF: +- info.si_code = TARGET_FPE_FLTOVF; +- break; +- case TARGET_GEN_FLTUND: +- info.si_code = TARGET_FPE_FLTUND; +- break; +- case TARGET_GEN_FLTINV: +- info.si_code = TARGET_FPE_FLTINV; +- break; +- case TARGET_GEN_FLTINE: +- info.si_code = TARGET_FPE_FLTRES; +- break; +- case TARGET_GEN_ROPRAND: +- info.si_code = 0; +- break; +- default: +- info.si_signo = TARGET_SIGTRAP; +- info.si_code = 0; +- break; ++ if (trapnr == EXCP01_DB) { ++ info.si_code = TARGET_TRAP_BRKPT; ++ info._sifields._sigfault._addr = env->eip; ++ } else { ++ info.si_code = TARGET_SI_KERNEL; ++ info._sifields._sigfault._addr = 0; + } +- info.si_errno = 0; +- info._sifields._sigfault._addr = env->pc; + queue_signal(env, info.si_signo, &info); +- break; +- default: +- goto do_sigill; + } + break; +- case EXCP_DEBUG: +- info.si_signo = gdb_handlesig(cs, TARGET_SIGTRAP); +- if (info.si_signo) { +- env->lock_addr = -1; ++ case EXCP04_INTO: ++ case EXCP05_BOUND: ++ assert (!(env->eflags & VM_MASK)); /* Not _that_ old :) */ ++ { ++ info.si_signo = TARGET_SIGSEGV; + info.si_errno = 0; +- info.si_code = TARGET_TRAP_BRKPT; ++ info.si_code = TARGET_SI_KERNEL; ++ info._sifields._sigfault._addr = 0; + queue_signal(env, info.si_signo, &info); + } + break; +- case EXCP_STL_C: +- case EXCP_STQ_C: +- do_store_exclusive(env, env->error_code, trapnr - EXCP_STL_C); +- break; +- case EXCP_INTERRUPT: +- /* Just indicate that signals should be handled asap. */ ++ case EXCP06_ILLOP: ++ info.si_signo = TARGET_SIGILL; ++ info.si_errno = 0; ++ info.si_code = TARGET_ILL_ILLOPN; ++ info._sifields._sigfault._addr = env->eip; ++ queue_signal(env, info.si_signo, &info); + break; +- default: +- printf ("Unhandled trap: 0x%x\n", trapnr); +- cpu_dump_state(cs, stderr, fprintf, 0); +- exit (1); +- } +- process_pending_signals (env); +- } +-} +-#endif /* TARGET_ALPHA */ +- +-#ifdef TARGET_S390X +-void cpu_loop(CPUS390XState *env) +-{ +- CPUState *cs = CPU(s390_env_get_cpu(env)); +- int trapnr, n, sig; +- target_siginfo_t info; +- target_ulong addr; +- +- while (1) { +- cpu_exec_start(cs); +- trapnr = cpu_s390x_exec(env); +- cpu_exec_end(cs); +- switch (trapnr) { + case EXCP_INTERRUPT: +- /* Just indicate that signals should be handled asap. */ +- break; +- +- case EXCP_SVC: +- n = env->int_svc_code; +- if (!n) { +- /* syscalls > 255 */ +- n = env->regs[1]; +- } +- env->psw.addr += env->int_svc_ilen; +- env->regs[2] = do_syscall(env, n, env->regs[2], env->regs[3], +- env->regs[4], env->regs[5], +- env->regs[6], env->regs[7], 0, 0); ++ /* just indicate that signals should be handled asap */ + break; +- + case EXCP_DEBUG: +- sig = gdb_handlesig(cs, TARGET_SIGTRAP); +- if (sig) { +- n = TARGET_TRAP_BRKPT; +- goto do_signal_pc; +- } +- break; +- case EXCP_PGM: +- n = env->int_pgm_code; +- switch (n) { +- case PGM_OPERATION: +- case PGM_PRIVILEGED: +- sig = TARGET_SIGILL; +- n = TARGET_ILL_ILLOPC; +- goto do_signal_pc; +- case PGM_PROTECTION: +- case PGM_ADDRESSING: +- sig = TARGET_SIGSEGV; +- /* XXX: check env->error_code */ +- n = TARGET_SEGV_MAPERR; +- addr = env->__excp_addr; +- goto do_signal; +- case PGM_EXECUTE: +- case PGM_SPECIFICATION: +- case PGM_SPECIAL_OP: +- case PGM_OPERAND: +- do_sigill_opn: +- sig = TARGET_SIGILL; +- n = TARGET_ILL_ILLOPN; +- goto do_signal_pc; +- +- case PGM_FIXPT_OVERFLOW: +- sig = TARGET_SIGFPE; +- n = TARGET_FPE_INTOVF; +- goto do_signal_pc; +- case PGM_FIXPT_DIVIDE: +- sig = TARGET_SIGFPE; +- n = TARGET_FPE_INTDIV; +- goto do_signal_pc; +- +- case PGM_DATA: +- n = (env->fpc >> 8) & 0xff; +- if (n == 0xff) { +- /* compare-and-trap */ +- goto do_sigill_opn; +- } else { +- /* An IEEE exception, simulated or otherwise. */ +- if (n & 0x80) { +- n = TARGET_FPE_FLTINV; +- } else if (n & 0x40) { +- n = TARGET_FPE_FLTDIV; +- } else if (n & 0x20) { +- n = TARGET_FPE_FLTOVF; +- } else if (n & 0x10) { +- n = TARGET_FPE_FLTUND; +- } else if (n & 0x08) { +- n = TARGET_FPE_FLTRES; +- } else { +- /* ??? Quantum exception; BFP, DFP error. */ +- goto do_sigill_opn; +- } +- sig = TARGET_SIGFPE; +- goto do_signal_pc; +- } ++ { ++ int sig; + +- default: +- fprintf(stderr, "Unhandled program exception: %#x\n", n); +- cpu_dump_state(cs, stderr, fprintf, 0); +- exit(1); ++ sig = gdb_handlesig(cs, TARGET_SIGTRAP); ++ if (sig) ++ { ++ info.si_signo = sig; ++ info.si_errno = 0; ++ info.si_code = TARGET_TRAP_BRKPT; ++ queue_signal(env, info.si_signo, &info); ++ } + } + break; +- +- do_signal_pc: +- addr = env->psw.addr; +- do_signal: +- info.si_signo = sig; +- info.si_errno = 0; +- info.si_code = n; +- info._sifields._sigfault._addr = addr; +- queue_signal(env, info.si_signo, &info); +- break; +- ++ case EXCP_SYSCALL: ++ fprintf(stderr, "qemu: attempted a SYSCALL - only int 0x80 is legal in CGC\n"); + default: +- fprintf(stderr, "Unhandled trap: 0x%x\n", trapnr); +- cpu_dump_state(cs, stderr, fprintf, 0); +- exit(1); ++ pc = env->segs[R_CS].base + env->eip; ++ fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n", ++ (long)pc, trapnr); ++ exit(-34); + } +- process_pending_signals (env); ++ process_pending_signals(env); + } + } + +-#endif /* TARGET_S390X */ ++ ++ + + THREAD CPUState *thread_cpu; + +@@ -3437,14 +424,6 @@ void stop_all_tasks(void) + /* Assumes contents are already zeroed. */ + void init_task_state(TaskState *ts) + { +- int i; +- +- ts->used = 1; +- ts->first_free = ts->sigqueue_table; +- for (i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++) { +- ts->sigqueue_table[i].next = &ts->sigqueue_table[i + 1]; +- } +- ts->sigqueue_table[i].next = NULL; + } + + CPUArchState *cpu_copy(CPUArchState *env) +@@ -3497,157 +476,131 @@ static void handle_arg_log_filename(const char *arg) + qemu_set_log_filename(arg); + } + +-static void handle_arg_set_env(const char *arg) ++static void handle_arg_randseed(const char *arg) + { +- char *r, *p, *token; +- r = p = strdup(arg); +- while ((token = strsep(&p, ",")) != NULL) { +- if (envlist_setenv(envlist, token) != 0) { +- usage(); +- } +- } +- free(r); +-} ++ unsigned long long seed; + +-static void handle_arg_unset_env(const char *arg) +-{ +- char *r, *p, *token; +- r = p = strdup(arg); +- while ((token = strsep(&p, ",")) != NULL) { +- if (envlist_unsetenv(envlist, token) != 0) { +- usage(); +- } ++ if (parse_uint_full(arg, &seed, 0) != 0 || seed > UINT_MAX) { ++ fprintf(stderr, "Invalid seed number: %s\n", arg); ++ exit(1); + } +- free(r); ++ ++ seed_passed = 1; ++ ++ srand(seed); + } + +-static void handle_arg_argv0(const char *arg) ++static void handle_arg_gdb(const char *arg) + { +- argv0 = strdup(arg); ++ gdbstub_port = atoi(arg); + } + +-static void handle_arg_stack_size(const char *arg) ++#if defined(CONFIG_USE_GUEST_BASE) ++static void handle_arg_guest_base(const char *arg) + { +- char *p; +- guest_stack_size = strtoul(arg, &p, 0); +- if (guest_stack_size == 0) { +- usage(); +- } +- +- if (*p == 'M') { +- guest_stack_size *= 1024 * 1024; +- } else if (*p == 'k' || *p == 'K') { +- guest_stack_size *= 1024; +- } ++ guest_base = strtol(arg, NULL, 0); ++ have_guest_base = 1; + } ++#endif + +-static void handle_arg_ld_prefix(const char *arg) ++static void handle_arg_singlestep(const char *arg) + { +- interp_prefix = strdup(arg); ++ singlestep = 1; + } + +-static void handle_arg_pagesize(const char *arg) ++static void handle_arg_strace(const char *arg) + { +- qemu_host_page_size = atoi(arg); +- if (qemu_host_page_size == 0 || +- (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) { +- fprintf(stderr, "page size must be a power of two\n"); +- exit(1); +- } ++ do_strace = 1; + } + +-static void handle_arg_randseed(const char *arg) ++static void handle_arg_version(const char *arg) + { +- unsigned long long seed; ++ printf("qemu-" TARGET_NAME " version " QEMU_VERSION QEMU_PKGVERSION ++ ", Copyright (c) 2003-2008 Fabrice Bellard\nSHELLPHISH MODDED FOR CGC, ASK Nick or Jacopo\n"); + +- if (parse_uint_full(arg, &seed, 0) != 0 || seed > UINT_MAX) { +- fprintf(stderr, "Invalid seed number: %s\n", arg); +- exit(1); +- } +- srand(seed); ++#ifdef TRACER ++ printf("Configured with -DTRACER\n"); ++#endif ++#ifdef AFL ++ printf("Configured with -DAFL\n"); ++#endif ++#if !defined(TRACER) && !defined(AFL) ++ printf("[base config version]\n"); ++#endif ++#ifdef ENFORCE_NX ++ printf("[will enforce NX]\n"); ++#endif ++ exit(0); + } + +-static void handle_arg_gdb(const char *arg) ++#ifdef TRACER ++static void handle_predump(const char *arg) + { +- gdbstub_port = atoi(arg); ++ predump_file = arg; + } ++#endif + +-static void handle_arg_uname(const char *arg) ++static void handle_memory_limit(const char *arg) + { +- qemu_uname_release = strdup(arg); +-} ++ struct rlimit r; ++ unsigned long long mem_limit; ++ char suffix; + +-static void handle_arg_cpu(const char *arg) +-{ +- cpu_model = strdup(arg); +- if (cpu_model == NULL || is_help_option(cpu_model)) { +- /* XXX: implement xxx_cpu_list for targets that still miss it */ +-#if defined(cpu_list) +- cpu_list(stdout, &fprintf); +-#endif ++ /* stripped from AFL */ ++ if (sscanf(arg, "%llu%c", &mem_limit, &suffix) < 1) { ++ printf("bad syntax used for -m\n"); + exit(1); + } ++ ++ switch (suffix) { ++ case 'T': mem_limit *= 1024 * 1024; break; ++ case 'G': mem_limit *= 1024; break; ++ case 'k': mem_limit /= 1024; break; ++ case 'M': break; ++ ++ default: printf("Unsupported suffix\n"); exit(1); ++ } ++ ++ r.rlim_max = r.rlim_cur = mem_limit << 20; ++ ++ setrlimit(RLIMIT_AS, &r); ++ + } + +-#if defined(CONFIG_USE_GUEST_BASE) +-static void handle_arg_guest_base(const char *arg) ++static void handle_report_bad_args(const char *arg) + { +- guest_base = strtol(arg, NULL, 0); +- have_guest_base = 1; ++ report_bad_args = 1; + } + +-static void handle_arg_reserved_va(const char *arg) ++static void handle_receive_count(const char *arg) + { +- char *p; +- int shift = 0; +- reserved_va = strtoul(arg, &p, 0); +- switch (*p) { +- case 'k': +- case 'K': +- shift = 10; +- break; +- case 'M': +- shift = 20; +- break; +- case 'G': +- shift = 30; +- break; +- } +- if (shift) { +- unsigned long unshifted = reserved_va; +- p++; +- reserved_va <<= shift; +- if (((reserved_va >> shift) != unshifted) +-#if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS +- || (reserved_va > (1ul << TARGET_VIRT_ADDR_SPACE_BITS)) +-#endif +- ) { +- fprintf(stderr, "Reserved virtual address too big\n"); ++ receive_count_fp = fopen(arg, "wb"); ++ if (!receive_count_fp) { ++ printf("failed to open receive_count file\n"); + exit(1); + } +- } +- if (*p) { +- fprintf(stderr, "Unrecognised -R size suffix '%s'\n", p); +- exit(1); +- } ++ ++ setvbuf(receive_count_fp, NULL, _IOLBF, 0); + } +-#endif + +-static void handle_arg_singlestep(const char *arg) ++static void handle_enable_double_empty_exiting(const char *arg) + { +- singlestep = 1; ++ enabled_double_empty_exiting = 1; + } + +-static void handle_arg_strace(const char *arg) ++static void handle_arg_magicdump(const char *arg) + { +- do_strace = 1; ++ magicdump_filename = strdup(arg); + } + +-static void handle_arg_version(const char *arg) ++static void handle_arg_magicpregen(const char *arg) + { +- printf("qemu-" TARGET_NAME " version " QEMU_VERSION QEMU_PKGVERSION +- ", Copyright (c) 2003-2008 Fabrice Bellard\n"); +- exit(0); ++ magicpregen_filename = strdup(arg); ++} ++ ++static void handle_arg_bitflip(const char *arg) ++{ ++ bitflip = 1; + } + + struct qemu_argument { +@@ -3664,41 +617,41 @@ static const struct qemu_argument arg_table[] = { + "", "print this help"}, + {"g", "QEMU_GDB", true, handle_arg_gdb, + "port", "wait gdb connection to 'port'"}, +- {"L", "QEMU_LD_PREFIX", true, handle_arg_ld_prefix, +- "path", "set the elf interpreter prefix to 'path'"}, +- {"s", "QEMU_STACK_SIZE", true, handle_arg_stack_size, +- "size", "set the stack size to 'size' bytes"}, +- {"cpu", "QEMU_CPU", true, handle_arg_cpu, +- "model", "select CPU (-cpu help for list)"}, +- {"E", "QEMU_SET_ENV", true, handle_arg_set_env, +- "var=value", "sets targets environment variable (see below)"}, +- {"U", "QEMU_UNSET_ENV", true, handle_arg_unset_env, +- "var", "unsets targets environment variable (see below)"}, +- {"0", "QEMU_ARGV0", true, handle_arg_argv0, +- "argv0", "forces target process argv[0] to be 'argv0'"}, +- {"r", "QEMU_UNAME", true, handle_arg_uname, +- "uname", "set qemu uname release string to 'uname'"}, + #if defined(CONFIG_USE_GUEST_BASE) + {"B", "QEMU_GUEST_BASE", true, handle_arg_guest_base, + "address", "set guest_base address to 'address'"}, +- {"R", "QEMU_RESERVED_VA", true, handle_arg_reserved_va, +- "size", "reserve 'size' bytes for guest virtual address space"}, + #endif + {"d", "QEMU_LOG", true, handle_arg_log, + "item[,...]", "enable logging of specified items " + "(use '-d help' for a list of items)"}, + {"D", "QEMU_LOG_FILENAME", true, handle_arg_log_filename, + "logfile", "write logs to 'logfile' (default stderr)"}, +- {"p", "QEMU_PAGESIZE", true, handle_arg_pagesize, +- "pagesize", "set the host page size to 'pagesize'"}, + {"singlestep", "QEMU_SINGLESTEP", false, handle_arg_singlestep, + "", "run in singlestep mode"}, + {"strace", "QEMU_STRACE", false, handle_arg_strace, + "", "log system calls"}, + {"seed", "QEMU_RAND_SEED", true, handle_arg_randseed, + "", "Seed for pseudo-random number generator"}, ++#ifdef TRACER ++ {"predump", "", true, handle_predump, ++ "", "File to dump state to at the point symbolic data is about to enter the program"}, ++#endif ++ {"m", "", true, handle_memory_limit, ++ "", "Set an upper limit on memory"}, ++ {"report_bad_args", "", false, handle_report_bad_args, ++ "", "Report potentially dangerous arguments passed to receive and transmit (with a SIGSEGV)"}, ++ {"receive_count", "", true, handle_receive_count, ++ "", "File to dump receive counting to"}, ++ {"enable_double_empty_exiting", "", false, handle_enable_double_empty_exiting, ++ "", "Enable the double empty exiting strategy"}, + {"version", "QEMU_VERSION", false, handle_arg_version, + "", "display version information and exit"}, ++ {"magicdump", "QEMU_MAGICDUMP", true, handle_arg_magicdump, ++ "", "dump CGC magic page contents to file"}, ++ {"bitflip", "QEMU_BITFLIP", false, handle_arg_bitflip, ++ "", "XOR with 0xFF every byte gotten via receive"}, ++ {"magicpregen","QEMU_MAGICPREGEN", true, handle_arg_magicpregen, ++ "", "read the flag page content from this file"}, + {NULL, NULL, false, NULL, NULL, NULL} + }; + +@@ -3750,9 +703,7 @@ static void usage(void) + + printf("\n" + "Defaults:\n" +- "QEMU_LD_PREFIX = %s\n" + "QEMU_STACK_SIZE = %ld byte\n", +- interp_prefix, + guest_stack_size); + + printf("\n" +@@ -3843,43 +794,40 @@ int main(int argc, char **argv, char **envp) + TaskState *ts; + CPUArchState *env; + CPUState *cpu; +- int optind; +- char **target_environ, **wrk; +- char **target_argv; +- int target_argc; +- int i; + int ret; + int execfd; + +- module_call_init(MODULE_INIT_QOM); +- +- if ((envlist = envlist_create()) == NULL) { +- (void) fprintf(stderr, "Unable to allocate envlist\n"); +- exit(1); ++ /* CGC binaries have STICKY_TIMEOUTS and ADDR_NO_RANDOMIZE set by default, ++ * but I rely on STICKY_TIMEOUTS to _not_ be set (I just don't copy the parameters back). ++ * The utility of ADDR_NO_RANDOMIZE is also somewhat questionable, but I still take care of it. */ ++ unsigned long persona = (unsigned long) personality(0xffffffff); ++ if ((persona & STICKY_TIMEOUTS) == STICKY_TIMEOUTS) { ++ fprintf(stderr, "qemu: do NOT set STICKY_TIMEOUTS, I handle that myself and I use the default timeout modification.\n"); ++ exit(11); + } +- +- /* add current environment into the list */ +- for (wrk = environ; *wrk != NULL; wrk++) { +- (void) envlist_setenv(envlist, *wrk); ++ /* ++ if ((persona & ADDR_NO_RANDOMIZE) != ADDR_NO_RANDOMIZE) { ++ if (personality(persona | ADDR_NO_RANDOMIZE) == -1) ++ err(1, "Couldn't set ADDR_NO_RANDOMIZE!"); ++ execv(argv[0], argv); ++ err(1, "Could not re-exec myself to disable ASLR! That's weird..."); + } ++ */ ++ ++ module_call_init(MODULE_INIT_QOM); + +- /* Read the stack limit from the kernel. If it's "unlimited", +- then we can do little else besides use the default. */ +- { +- struct rlimit lim; +- if (getrlimit(RLIMIT_STACK, &lim) == 0 +- && lim.rlim_cur != RLIM_INFINITY +- && lim.rlim_cur == (target_long)lim.rlim_cur) { +- guest_stack_size = lim.rlim_cur; +- } +- } + + cpu_model = NULL; + #if defined(cpudef_setup) + cpudef_setup(); /* parse cpu definitions in target config file (TBD) */ + #endif + +- srand(time(NULL)); ++#if defined(TRACER) || defined(AFL) ++ enabled_double_empty_exiting = 1; ++#endif ++ ++ /* we want rand to be consistent across runs (when the seed is not specified) */ ++ srand(0); + + optind = parse_args(argc, argv); + +@@ -3894,44 +842,8 @@ int main(int argc, char **argv, char **envp) + /* Scan interp_prefix dir for replacement files. */ + init_paths(interp_prefix); + +- init_qemu_uname_release(); +- + if (cpu_model == NULL) { +-#if defined(TARGET_I386) +-#ifdef TARGET_X86_64 +- cpu_model = "qemu64"; +-#else + cpu_model = "qemu32"; +-#endif +-#elif defined(TARGET_ARM) +- cpu_model = "any"; +-#elif defined(TARGET_UNICORE32) +- cpu_model = "any"; +-#elif defined(TARGET_M68K) +- cpu_model = "any"; +-#elif defined(TARGET_SPARC) +-#ifdef TARGET_SPARC64 +- cpu_model = "TI UltraSparc II"; +-#else +- cpu_model = "Fujitsu MB86904"; +-#endif +-#elif defined(TARGET_MIPS) +-#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) +- cpu_model = "5KEf"; +-#else +- cpu_model = "24Kf"; +-#endif +-#elif defined TARGET_OPENRISC +- cpu_model = "or1200"; +-#elif defined(TARGET_PPC) +-# ifdef TARGET_PPC64 +- cpu_model = "POWER7"; +-# else +- cpu_model = "750"; +-# endif +-#else +- cpu_model = "any"; +-#endif + } + tcg_exec_init(0); + cpu_exec_init_all(); +@@ -3955,9 +867,6 @@ int main(int argc, char **argv, char **envp) + handle_arg_randseed(getenv("QEMU_RAND_SEED")); + } + +- target_environ = envlist_to_environ(envlist, NULL); +- envlist_free(envlist); +- + #if defined(CONFIG_USE_GUEST_BASE) + /* + * Now that page sizes are configured in cpu_init() we can do +@@ -3980,6 +889,8 @@ int main(int argc, char **argv, char **envp) + mmap_next_start = reserved_va; + } + } ++#else /* CONFIG_USE_GUEST_BASE */ ++# error CGC (x86) has guest base! + #endif /* CONFIG_USE_GUEST_BASE */ + + /* +@@ -4000,29 +911,6 @@ int main(int argc, char **argv, char **envp) + } + } + +- /* +- * Prepare copy of argv vector for target. +- */ +- target_argc = argc - optind; +- target_argv = calloc(target_argc + 1, sizeof (char *)); +- if (target_argv == NULL) { +- (void) fprintf(stderr, "Unable to allocate memory for target_argv\n"); +- exit(1); +- } +- +- /* +- * If argv0 is specified (using '-0' switch) we replace +- * argv[0] pointer with the given one. +- */ +- i = 0; +- if (argv0 != NULL) { +- target_argv[i++] = strdup(argv0); +- } +- for (; i < target_argc; i++) { +- target_argv[i] = strdup(argv[optind + i]); +- } +- target_argv[target_argc] = NULL; +- + ts = g_malloc0 (sizeof(TaskState)); + init_task_state(ts); + /* build Task State */ +@@ -4040,26 +928,20 @@ int main(int argc, char **argv, char **envp) + } + } + +- ret = loader_exec(execfd, filename, target_argv, target_environ, regs, ++ ret = loader_exec(execfd, filename, NULL, NULL, regs, + info, &bprm); + if (ret != 0) { + printf("Error while loading %s: %s\n", filename, strerror(-ret)); + _exit(1); + } + +- for (wrk = target_environ; *wrk; wrk++) { +- free(*wrk); +- } +- +- free(target_environ); +- + if (qemu_log_enabled()) { + #if defined(CONFIG_USE_GUEST_BASE) + qemu_log("guest_base 0x%lx\n", guest_base); + #endif + log_page_dump(); + +- qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk); ++ qemu_log("IGNORED start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk); + qemu_log("end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code); + qemu_log("start_code 0x" TARGET_ABI_FMT_lx "\n", + info->start_code); +@@ -4072,7 +954,8 @@ int main(int argc, char **argv, char **envp) + qemu_log("entry 0x" TARGET_ABI_FMT_lx "\n", info->entry); + } + +- target_set_brk(info->brk); ++ /* CGC TODO: should this be kept somehow? */ ++ /* target_set_brk(info->brk); */ + syscall_init(); + signal_init(); + +@@ -4091,14 +974,7 @@ int main(int argc, char **argv, char **envp) + env->hflags |= HF_OSFXSR_MASK; + } + #ifndef TARGET_ABI32 +- /* enable 64 bit mode if possible */ +- if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) { +- fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n"); +- exit(1); +- } +- env->cr[4] |= CR4_PAE_MASK; +- env->efer |= MSR_EFER_LMA | MSR_EFER_LME; +- env->hflags |= HF_LMA_MASK; ++# error CGC is 32-bit only! + #endif + + /* flags setup : we activate the IRQs by default as in user mode */ +@@ -4106,15 +982,7 @@ int main(int argc, char **argv, char **envp) + + /* linux register setup */ + #ifndef TARGET_ABI32 +- env->regs[R_EAX] = regs->rax; +- env->regs[R_EBX] = regs->rbx; +- env->regs[R_ECX] = regs->rcx; +- env->regs[R_EDX] = regs->rdx; +- env->regs[R_ESI] = regs->rsi; +- env->regs[R_EDI] = regs->rdi; +- env->regs[R_EBP] = regs->rbp; +- env->regs[R_ESP] = regs->rsp; +- env->eip = regs->rip; ++# error CGC is 32-bit only! + #else + env->regs[R_EAX] = regs->eax; + env->regs[R_EBX] = regs->ebx; +@@ -4128,12 +996,14 @@ int main(int argc, char **argv, char **envp) + #endif + + /* linux interrupt setup */ ++ /* NOTE: mmap_next_start is still at reserved_va here, so it will go right ++ * before the "kernel break" at 0x7f... */ + #ifndef TARGET_ABI32 +- env->idt.limit = 511; ++# error CGC is 32-bit only! + #else + env->idt.limit = 255; + #endif +- env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1), ++ env->idt.base = target_mmap(CGC_IDT_BASE, sizeof(uint64_t) * (env->idt.limit + 1), + PROT_READ|PROT_WRITE, + MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); + idt_table = g2h(env->idt.base); +@@ -4162,7 +1032,8 @@ int main(int argc, char **argv, char **envp) + /* linux segment setup */ + { + uint64_t *gdt_table; +- env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES, ++ unsigned int gdt_base = ((((CGC_IDT_BASE + sizeof(uint64_t) * (env->idt.limit + 1)) / 0x1000) + 1) * 0x1000); ++ env->gdt.base = target_mmap(gdt_base, sizeof(uint64_t) * TARGET_GDT_ENTRIES, + PROT_READ|PROT_WRITE, + MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); + env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1; +@@ -4172,11 +1043,7 @@ int main(int argc, char **argv, char **envp) + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | + (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT)); + #else +- /* 64 bit code segment */ +- write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff, +- DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | +- DESC_L_MASK | +- (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT)); ++# error CGC is 32-bit only! + #endif + write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff, + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | +@@ -4189,217 +1056,13 @@ int main(int argc, char **argv, char **envp) + cpu_x86_load_seg(env, R_ES, __USER_DS); + cpu_x86_load_seg(env, R_FS, __USER_DS); + cpu_x86_load_seg(env, R_GS, __USER_DS); +- /* This hack makes Wine work... */ +- env->segs[R_FS].selector = 0; +-#else +- cpu_x86_load_seg(env, R_DS, 0); +- cpu_x86_load_seg(env, R_ES, 0); +- cpu_x86_load_seg(env, R_FS, 0); +- cpu_x86_load_seg(env, R_GS, 0); +-#endif +-#elif defined(TARGET_AARCH64) +- { +- int i; +- +- if (!(arm_feature(env, ARM_FEATURE_AARCH64))) { +- fprintf(stderr, +- "The selected ARM CPU does not support 64 bit mode\n"); +- exit(1); +- } +- +- for (i = 0; i < 31; i++) { +- env->xregs[i] = regs->regs[i]; +- } +- env->pc = regs->pc; +- env->xregs[31] = regs->sp; +- } +-#elif defined(TARGET_ARM) +- { +- int i; +- cpsr_write(env, regs->uregs[16], 0xffffffff); +- for(i = 0; i < 16; i++) { +- env->regs[i] = regs->uregs[i]; +- } +- /* Enable BE8. */ +- if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4 +- && (info->elf_flags & EF_ARM_BE8)) { +- env->bswap_code = 1; +- } +- } +-#elif defined(TARGET_UNICORE32) +- { +- int i; +- cpu_asr_write(env, regs->uregs[32], 0xffffffff); +- for (i = 0; i < 32; i++) { +- env->regs[i] = regs->uregs[i]; +- } +- } +-#elif defined(TARGET_SPARC) +- { +- int i; +- env->pc = regs->pc; +- env->npc = regs->npc; +- env->y = regs->y; +- for(i = 0; i < 8; i++) +- env->gregs[i] = regs->u_regs[i]; +- for(i = 0; i < 8; i++) +- env->regwptr[i] = regs->u_regs[i + 8]; +- } +-#elif defined(TARGET_PPC) +- { +- int i; +- +-#if defined(TARGET_PPC64) +-#if defined(TARGET_ABI32) +- env->msr &= ~((target_ulong)1 << MSR_SF); + #else +- env->msr |= (target_ulong)1 << MSR_SF; +-#endif ++# error CGC is 32-bit only! + #endif +- env->nip = regs->nip; +- for(i = 0; i < 32; i++) { +- env->gpr[i] = regs->gpr[i]; +- } +- } +-#elif defined(TARGET_M68K) +- { +- env->pc = regs->pc; +- env->dregs[0] = regs->d0; +- env->dregs[1] = regs->d1; +- env->dregs[2] = regs->d2; +- env->dregs[3] = regs->d3; +- env->dregs[4] = regs->d4; +- env->dregs[5] = regs->d5; +- env->dregs[6] = regs->d6; +- env->dregs[7] = regs->d7; +- env->aregs[0] = regs->a0; +- env->aregs[1] = regs->a1; +- env->aregs[2] = regs->a2; +- env->aregs[3] = regs->a3; +- env->aregs[4] = regs->a4; +- env->aregs[5] = regs->a5; +- env->aregs[6] = regs->a6; +- env->aregs[7] = regs->usp; +- env->sr = regs->sr; +- ts->sim_syscalls = 1; +- } +-#elif defined(TARGET_MICROBLAZE) +- { +- env->regs[0] = regs->r0; +- env->regs[1] = regs->r1; +- env->regs[2] = regs->r2; +- env->regs[3] = regs->r3; +- env->regs[4] = regs->r4; +- env->regs[5] = regs->r5; +- env->regs[6] = regs->r6; +- env->regs[7] = regs->r7; +- env->regs[8] = regs->r8; +- env->regs[9] = regs->r9; +- env->regs[10] = regs->r10; +- env->regs[11] = regs->r11; +- env->regs[12] = regs->r12; +- env->regs[13] = regs->r13; +- env->regs[14] = regs->r14; +- env->regs[15] = regs->r15; +- env->regs[16] = regs->r16; +- env->regs[17] = regs->r17; +- env->regs[18] = regs->r18; +- env->regs[19] = regs->r19; +- env->regs[20] = regs->r20; +- env->regs[21] = regs->r21; +- env->regs[22] = regs->r22; +- env->regs[23] = regs->r23; +- env->regs[24] = regs->r24; +- env->regs[25] = regs->r25; +- env->regs[26] = regs->r26; +- env->regs[27] = regs->r27; +- env->regs[28] = regs->r28; +- env->regs[29] = regs->r29; +- env->regs[30] = regs->r30; +- env->regs[31] = regs->r31; +- env->sregs[SR_PC] = regs->pc; +- } +-#elif defined(TARGET_MIPS) +- { +- int i; +- +- for(i = 0; i < 32; i++) { +- env->active_tc.gpr[i] = regs->regs[i]; +- } +- env->active_tc.PC = regs->cp0_epc & ~(target_ulong)1; +- if (regs->cp0_epc & 1) { +- env->hflags |= MIPS_HFLAG_M16; +- } +- } +-#elif defined(TARGET_OPENRISC) +- { +- int i; +- +- for (i = 0; i < 32; i++) { +- env->gpr[i] = regs->gpr[i]; +- } +- +- env->sr = regs->sr; +- env->pc = regs->pc; +- } +-#elif defined(TARGET_SH4) +- { +- int i; +- +- for(i = 0; i < 16; i++) { +- env->gregs[i] = regs->regs[i]; +- } +- env->pc = regs->pc; +- } +-#elif defined(TARGET_ALPHA) +- { +- int i; +- +- for(i = 0; i < 28; i++) { +- env->ir[i] = ((abi_ulong *)regs)[i]; +- } +- env->ir[IR_SP] = regs->usp; +- env->pc = regs->pc; +- } +-#elif defined(TARGET_CRIS) +- { +- env->regs[0] = regs->r0; +- env->regs[1] = regs->r1; +- env->regs[2] = regs->r2; +- env->regs[3] = regs->r3; +- env->regs[4] = regs->r4; +- env->regs[5] = regs->r5; +- env->regs[6] = regs->r6; +- env->regs[7] = regs->r7; +- env->regs[8] = regs->r8; +- env->regs[9] = regs->r9; +- env->regs[10] = regs->r10; +- env->regs[11] = regs->r11; +- env->regs[12] = regs->r12; +- env->regs[13] = regs->r13; +- env->regs[14] = info->start_stack; +- env->regs[15] = regs->acr; +- env->pc = regs->erp; +- } +-#elif defined(TARGET_S390X) +- { +- int i; +- for (i = 0; i < 16; i++) { +- env->regs[i] = regs->gprs[i]; +- } +- env->psw.mask = regs->psw.mask; +- env->psw.addr = regs->psw.addr; +- } + #else + #error unsupported target CPU + #endif + +-#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32) +- ts->stack_base = info->start_stack; +- ts->heap_base = info->brk; +- /* This will be filled in on the first SYS_HEAPINFO call. */ +- ts->heap_limit = 0; +-#endif + + if (gdbstub_port) { + if (gdbserver_start(gdbstub_port) < 0) { +@@ -4409,6 +1072,31 @@ int main(int argc, char **argv, char **envp) + } + gdb_handlesig(cpu, 0); + } ++ ++ /* Placed to get allocate to behave just like the CGC CQE VM, there's ++ probably a more natural way to have this occur... ++ Also note: this is currently being changed back and forth. ++ - unspecified ELF load addresses (never happens, right? kept at standard ELF 8000000) ++ - IDT / GDT / etc. (kept at qemu's default of going right before the kernel break == reserved_va) ++ - allocate() --> CHANGING IT HERE <-- ++ */ ++ mmap_next_start = 0xb8000000; ++ // NOTE: DO NOT CHANGE reserved_va, otherwise self-modifying code detection will break! [J] ++ ++ /* Final check against the official https://github.com/CyberGrandChallenge/libcgc/blob/master/cgcabi.md */ ++ assert(env->regs[R_EAX] == 0); assert(env->regs[R_EBX] == 0); ++ assert(env->regs[R_ECX] == CGC_MAGIC_PAGE_ADDR); // Note: fixed (for CFE) ++ assert(env->regs[R_EDX] == 0); assert(env->regs[R_EDI] == 0); assert(env->regs[R_ESI] == 0); ++ assert(env->regs[R_ESP] == 0xbaaaaffc); ++ assert(env->eflags == 0x202); ++ assert(env->regs[R_ES] == env->regs[R_DS]); ++ assert(env->regs[R_SS] == env->regs[R_DS]); ++ assert(env->regs[R_GS] == env->regs[R_DS]); ++ ++ // This actually works, even though this is not true (yet?) ++ // Maybe some reset happening later? [J] ++ //assert(env->regs[R_FS] == env->regs[R_DS]); ++ + cpu_loop(env); + /* never exits */ + return 0; +diff --git a/home/gkrishna/Shelly/work/qemu/linux-user/mmap.c b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/mmap.c +index a249f0c..ac77fcb 100644 +--- a/home/gkrishna/Shelly/work/qemu/linux-user/mmap.c ++++ b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/mmap.c +@@ -194,16 +194,16 @@ static int mmap_frag(abi_ulong real_start, + } + + #if HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 64 +-# define TASK_UNMAPPED_BASE (1ul << 38) ++# error NOT CGC! + #elif defined(__CYGWIN__) +-/* Cygwin doesn't have a whole lot of address space. */ +-# define TASK_UNMAPPED_BASE 0x18000000 ++# error NOT CGC! + #else +-# define TASK_UNMAPPED_BASE 0x40000000 ++/* Changed the value for CGC (was 0x40000000) */ ++# define TASK_UNMAPPED_BASE 0xbaaab000 + #endif + abi_ulong mmap_next_start = TASK_UNMAPPED_BASE; + +-unsigned long last_brk; ++// unsigned long last_brk; + + #ifdef CONFIG_USE_GUEST_BASE + /* Subroutine of mmap_find_vma, used when we have pre-allocated a chunk +diff --git a/home/gkrishna/Shelly/work/qemu/linux-user/qemu.h b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/qemu.h +index 8012cc2..48d1abc 100644 +--- a/home/gkrishna/Shelly/work/qemu/linux-user/qemu.h ++++ b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/qemu.h +@@ -22,6 +22,10 @@ + + #define THREAD __thread + ++/* https://github.com/CyberGrandChallenge/libcgc/blob/master/cgcabi.md */ ++#define CGC_MAGIC_PAGE_ADDR 0x4347c000 ++#define CGC_INITIAL_SP 0xbaaaaffcu ++ + /* This struct is used to hold certain information about the image. + * Basically, it replicates in user space what would be certain + * task_struct fields in the kernel +@@ -58,23 +62,6 @@ struct image_info { + #endif + }; + +-#ifdef TARGET_I386 +-/* Information about the current linux thread */ +-struct vm86_saved_state { +- uint32_t eax; /* return code */ +- uint32_t ebx; +- uint32_t ecx; +- uint32_t edx; +- uint32_t esi; +- uint32_t edi; +- uint32_t ebp; +- uint32_t esp; +- uint32_t eflags; +- uint32_t eip; +- uint16_t cs, ss, ds, es, fs, gs; +-}; +-#endif +- + #if defined(TARGET_ARM) && defined(TARGET_ABI32) + /* FPU emulator */ + #include "nwfpe/fpa11.h" +@@ -87,6 +74,7 @@ struct sigqueue { + target_siginfo_t info; + }; + ++ + struct emulated_sigtable { + int pending; /* true if signal is pending */ + struct sigqueue *first; +@@ -94,37 +82,12 @@ struct emulated_sigtable { + first signal, we put it here */ + }; + ++ + /* NOTE: we force a big alignment so that the stack stored after is + aligned too */ + typedef struct TaskState { + pid_t ts_tid; /* tid (or pid) of this task */ +-#ifdef TARGET_ARM +-# ifdef TARGET_ABI32 +- /* FPA state */ +- FPA11 fpa; +-# endif +- int swi_errno; +-#endif +-#ifdef TARGET_UNICORE32 +- int swi_errno; +-#endif +-#if defined(TARGET_I386) && !defined(TARGET_X86_64) +- abi_ulong target_v86; +- struct vm86_saved_state vm86_saved_regs; +- struct target_vm86plus_struct vm86plus; +- uint32_t v86flags; +- uint32_t v86mask; +-#endif + abi_ulong child_tidptr; +-#ifdef TARGET_M68K +- int sim_syscalls; +- abi_ulong tp_value; +-#endif +-#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32) +- /* Extra fields for semihosted binaries. */ +- uint32_t heap_base; +- uint32_t heap_limit; +-#endif + uint32_t stack_base; + int used; /* non zero if used */ + bool sigsegv_blocked; /* SIGSEGV blocked by guest */ +@@ -181,12 +144,11 @@ int loader_exec(int fdexec, const char *filename, char **argv, char **envp, + struct linux_binprm *); + + int load_elf_binary(struct linux_binprm *bprm, struct image_info *info); +-int load_flt_binary(struct linux_binprm *bprm, struct image_info *info); + + abi_long memcpy_to_target(abi_ulong dest, const void *src, + unsigned long len); +-void target_set_brk(abi_ulong new_brk); +-abi_long do_brk(abi_ulong new_brk); ++//void target_set_brk(abi_ulong new_brk); ++//abi_long do_brk(abi_ulong new_brk); + void syscall_init(void); + abi_long do_syscall(void *cpu_env, int num, abi_long arg1, + abi_long arg2, abi_long arg3, abi_long arg4, +@@ -239,17 +201,6 @@ long do_rt_sigreturn(CPUArchState *env); + abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp); + int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset); + +-#ifdef TARGET_I386 +-/* vm86.c */ +-void save_v86_state(CPUX86State *env); +-void handle_vm86_trap(CPUX86State *env, int trapno); +-void handle_vm86_fault(CPUX86State *env); +-int do_vm86(CPUX86State *env, long subfunction, abi_ulong v86_addr); +-#elif defined(TARGET_SPARC64) +-void sparc64_set_context(CPUSPARCState *env); +-void sparc64_get_context(CPUSPARCState *env); +-#endif +- + /* mmap.c */ + int target_mprotect(abi_ulong start, abi_ulong len, int prot); + abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, +@@ -259,7 +210,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size, + abi_ulong new_size, unsigned long flags, + abi_ulong new_addr); + int target_msync(abi_ulong start, abi_ulong len, int flags); +-extern unsigned long last_brk; ++//extern unsigned long last_brk; + extern abi_ulong mmap_next_start; + void mmap_lock(void); + void mmap_unlock(void); +@@ -269,8 +220,12 @@ void cpu_list_unlock(void); + void mmap_fork_start(void); + void mmap_fork_end(int child); + ++/* linuxload.c */ ++extern char *magicdump_filename, *magicpregen_filename; ++ + /* main.c */ +-extern unsigned long guest_stack_size; ++static const unsigned long guest_stack_size = 8 * 1024 * 1024; //extern unsigned long guest_stack_size; ++extern int seed_passed; + + /* user access */ + +@@ -331,7 +286,7 @@ static inline int access_ok(int type, abi_ulong addr, abi_ulong size) + __put_user((x), __hptr); \ + unlock_user(__hptr, __gaddr, sizeof(target_type)); \ + } else \ +- __ret = -TARGET_EFAULT; \ ++ __ret = TARGET_EFAULT; \ + __ret; \ + }) + +@@ -346,7 +301,7 @@ static inline int access_ok(int type, abi_ulong addr, abi_ulong size) + } else { \ + /* avoid warning */ \ + (x) = 0; \ +- __ret = -TARGET_EFAULT; \ ++ __ret = TARGET_EFAULT; \ + } \ + __ret; \ + }) +@@ -425,7 +380,7 @@ static inline void unlock_user(void *host_ptr, abi_ulong guest_addr, + #endif + } + +-/* Return the length of a string in target memory or -TARGET_EFAULT if ++/* Return the length of a string in target memory or TARGET_EFAULT if + access error. */ + abi_long target_strlen(abi_ulong gaddr); + +@@ -447,12 +402,4 @@ static inline void *lock_user_string(abi_ulong guest_addr) + + #include + +-/* Include target-specific struct and function definitions; +- * they may need access to the target-independent structures +- * above, so include them last. +- */ +-#include "target_cpu.h" +-#include "target_signal.h" +-#include "target_structs.h" +- + #endif /* QEMU_H */ +diff --git a/home/gkrishna/Shelly/work/qemu/linux-user/signal.c b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/signal.c +index 5bb399e..6ff19f4 100644 +--- a/home/gkrishna/Shelly/work/qemu/linux-user/signal.c ++++ b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/signal.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -32,6 +33,9 @@ + + //#define DEBUG_SIGNAL + ++extern unsigned long cgc_stack_top; ++extern unsigned long max_stack_top; ++ + static struct target_sigaltstack target_sigaltstack_used = { + .ss_sp = 0, + .ss_size = 0, +@@ -461,6 +465,8 @@ static void QEMU_NORETURN force_sig(int target_sig) + getrlimit(RLIMIT_CORE, &nodump); + nodump.rlim_cur=0; + setrlimit(RLIMIT_CORE, &nodump); ++ qemu_log("qemu: uncaught target signal %d (%s) - %s [%08x]\n", ++ target_sig, strsignal(host_sig), "core dumped",env->eip); + (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) - %s\n", + target_sig, strsignal(host_sig), "core dumped" ); + } +@@ -576,6 +582,42 @@ static void host_signal_handler(int host_signum, siginfo_t *info, + int sig; + target_siginfo_t tinfo; + ++ /* handle stack growth ++ * Note: stack_top ~= "next push address" (lowest valid address) */ ++ unsigned long vaddr = (h2g_nocheck(info->si_addr) / 0x1000) * 0x1000; ++ if (host_signum == TARGET_SIGSEGV && vaddr >= max_stack_top && vaddr < cgc_stack_top) { ++#ifdef DEBUG_STACK ++ fprintf(stderr, "qemu: auto-growing stack of %ld pages (old top %#lx, new %#lx, segfault at %p)\n", ++ (cgc_stack_top-vaddr)/4096, cgc_stack_top, vaddr, info->si_addr); ++#endif ++ assert(((cgc_stack_top - vaddr) % 4096) == 0); ++ ++#ifdef STACK_GROW_1PG /* IMPRECISE, there are cases in which this is OK! See */ ++ if ((cgc_stack_top - vaddr) != 4096) { ++#ifdef DEBUG_STACK ++ fprintf(stderr, "qemu: FYI, forbidding stack growth of more than one page at the time! (%ld pages, vaddr=%#lx, segfault at %p)", ++ (cgc_stack_top-vaddr)/4096, vaddr, info->si_addr); ++#endif ++ } else ++#endif /* STACK_GROW_1PG */ ++ { ++ abi_ulong r = target_mmap(vaddr, cgc_stack_top - vaddr, PROT_READ | PROT_WRITE | PROT_EXEC, ++ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); ++ if (r != vaddr) { ++ fprintf(stderr, "Failed to grow the stack to vaddr=%#lx, diff %#lx!\n", vaddr, cgc_stack_top-vaddr); ++ fprintf(stderr, "target_mmap returned %u (%s)\n", r, strerror(r)); ++ exit(88); ++ } ++ cgc_stack_top = vaddr; ++ return; ++ } ++ } ++#ifdef DEBUG_STACK ++ if (host_signum == TARGET_SIGSEGV && vaddr < cgc_stack_top) { ++ fprintf(stderr, "qemu: FYI, going to fail due to excessive stack request. vaddr=%#lx\n", vaddr); ++ } ++#endif ++ + /* the CPU emulator uses some host signals to detect exceptions, + we forward to it some signals */ + if ((host_signum == SIGSEGV || host_signum == SIGBUS) +@@ -627,7 +669,7 @@ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp) + } + #endif + +- ret = -TARGET_EFAULT; ++ ret = TARGET_EFAULT; + if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)) { + goto out; + } +@@ -636,11 +678,11 @@ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp) + __get_user(ss.ss_flags, &uss->ss_flags); + unlock_user_struct(uss, uss_addr, 0); + +- ret = -TARGET_EPERM; ++ ret = TARGET_EINVAL; /* Was EPERM, impossible in CGC-world */ + if (on_sig_stack(sp)) + goto out; + +- ret = -TARGET_EINVAL; ++ ret = TARGET_EINVAL; + if (ss.ss_flags != TARGET_SS_DISABLE + && ss.ss_flags != TARGET_SS_ONSTACK + && ss.ss_flags != 0) +@@ -650,7 +692,7 @@ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp) + ss.ss_size = 0; + ss.ss_sp = 0; + } else { +- ret = -TARGET_ENOMEM; ++ ret = TARGET_ENOMEM; + if (ss.ss_size < minstacksize) { + goto out; + } +@@ -661,7 +703,7 @@ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp) + } + + if (uoss_addr) { +- ret = -TARGET_EFAULT; ++ ret = TARGET_EFAULT; + if (copy_to_user(uoss_addr, &oss, sizeof(oss))) + goto out; + } +@@ -835,44 +877,44 @@ struct rt_sigframe + */ + + /* XXX: save x87 state */ +-static void setup_sigcontext(struct target_sigcontext *sc, +- struct target_fpstate *fpstate, CPUX86State *env, abi_ulong mask, +- abi_ulong fpstate_addr) +-{ +- CPUState *cs = CPU(x86_env_get_cpu(env)); +- uint16_t magic; +- +- /* already locked in setup_frame() */ +- __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs); +- __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs); +- __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es); +- __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds); +- __put_user(env->regs[R_EDI], &sc->edi); +- __put_user(env->regs[R_ESI], &sc->esi); +- __put_user(env->regs[R_EBP], &sc->ebp); +- __put_user(env->regs[R_ESP], &sc->esp); +- __put_user(env->regs[R_EBX], &sc->ebx); +- __put_user(env->regs[R_EDX], &sc->edx); +- __put_user(env->regs[R_ECX], &sc->ecx); +- __put_user(env->regs[R_EAX], &sc->eax); +- __put_user(cs->exception_index, &sc->trapno); +- __put_user(env->error_code, &sc->err); +- __put_user(env->eip, &sc->eip); +- __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs); +- __put_user(env->eflags, &sc->eflags); +- __put_user(env->regs[R_ESP], &sc->esp_at_signal); +- __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss); +- +- cpu_x86_fsave(env, fpstate_addr, 1); +- fpstate->status = fpstate->sw; +- magic = 0xffff; +- __put_user(magic, &fpstate->magic); +- __put_user(fpstate_addr, &sc->fpstate); +- +- /* non-iBCS2 extensions.. */ +- __put_user(mask, &sc->oldmask); +- __put_user(env->cr[2], &sc->cr2); +-} ++//static void setup_sigcontext(struct target_sigcontext *sc, ++// struct target_fpstate *fpstate, CPUX86State *env, abi_ulong mask, ++// abi_ulong fpstate_addr) ++//{ ++// CPUState *cs = CPU(x86_env_get_cpu(env)); ++// uint16_t magic; ++// ++// /* already locked in setup_frame() */ ++// __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs); ++// __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs); ++// __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es); ++// __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds); ++// __put_user(env->regs[R_EDI], &sc->edi); ++// __put_user(env->regs[R_ESI], &sc->esi); ++// __put_user(env->regs[R_EBP], &sc->ebp); ++// __put_user(env->regs[R_ESP], &sc->esp); ++// __put_user(env->regs[R_EBX], &sc->ebx); ++// __put_user(env->regs[R_EDX], &sc->edx); ++// __put_user(env->regs[R_ECX], &sc->ecx); ++// __put_user(env->regs[R_EAX], &sc->eax); ++// __put_user(cs->exception_index, &sc->trapno); ++// __put_user(env->error_code, &sc->err); ++// __put_user(env->eip, &sc->eip); ++// __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs); ++// __put_user(env->eflags, &sc->eflags); ++// __put_user(env->regs[R_ESP], &sc->esp_at_signal); ++// __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss); ++// ++// cpu_x86_fsave(env, fpstate_addr, 1); ++// fpstate->status = fpstate->sw; ++// magic = 0xffff; ++// __put_user(magic, &fpstate->magic); ++// __put_user(fpstate_addr, &sc->fpstate); ++// ++// /* non-iBCS2 extensions.. */ ++// __put_user(mask, &sc->oldmask); ++// __put_user(env->cr[2], &sc->cr2); ++//} + + /* + * Determine which stack to use.. +@@ -902,135 +944,135 @@ get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size) + } + + /* compare linux/arch/i386/kernel/signal.c:setup_frame() */ +-static void setup_frame(int sig, struct target_sigaction *ka, +- target_sigset_t *set, CPUX86State *env) +-{ +- abi_ulong frame_addr; +- struct sigframe *frame; +- int i; +- +- frame_addr = get_sigframe(ka, env, sizeof(*frame)); +- +- if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) +- goto give_sigsegv; +- +- __put_user(sig, &frame->sig); +- +- setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0], +- frame_addr + offsetof(struct sigframe, fpstate)); +- +- for(i = 1; i < TARGET_NSIG_WORDS; i++) { +- __put_user(set->sig[i], &frame->extramask[i - 1]); +- } +- +- /* Set up to return from userspace. If provided, use a stub +- already in userspace. */ +- if (ka->sa_flags & TARGET_SA_RESTORER) { +- __put_user(ka->sa_restorer, &frame->pretcode); +- } else { +- uint16_t val16; +- abi_ulong retcode_addr; +- retcode_addr = frame_addr + offsetof(struct sigframe, retcode); +- __put_user(retcode_addr, &frame->pretcode); +- /* This is popl %eax ; movl $,%eax ; int $0x80 */ +- val16 = 0xb858; +- __put_user(val16, (uint16_t *)(frame->retcode+0)); +- __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2)); +- val16 = 0x80cd; +- __put_user(val16, (uint16_t *)(frame->retcode+6)); +- } +- +- +- /* Set up registers for signal handler */ +- env->regs[R_ESP] = frame_addr; +- env->eip = ka->_sa_handler; +- +- cpu_x86_load_seg(env, R_DS, __USER_DS); +- cpu_x86_load_seg(env, R_ES, __USER_DS); +- cpu_x86_load_seg(env, R_SS, __USER_DS); +- cpu_x86_load_seg(env, R_CS, __USER_CS); +- env->eflags &= ~TF_MASK; +- +- unlock_user_struct(frame, frame_addr, 1); +- +- return; +- +-give_sigsegv: +- if (sig == TARGET_SIGSEGV) +- ka->_sa_handler = TARGET_SIG_DFL; +- force_sig(TARGET_SIGSEGV /* , current */); +-} ++//static void setup_frame(int sig, struct target_sigaction *ka, ++// target_sigset_t *set, CPUX86State *env) ++//{ ++// abi_ulong frame_addr; ++// struct sigframe *frame; ++// int i; ++// ++// frame_addr = get_sigframe(ka, env, sizeof(*frame)); ++// ++// if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) ++// goto give_sigsegv; ++// ++// __put_user(sig, &frame->sig); ++// ++// setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0], ++// frame_addr + offsetof(struct sigframe, fpstate)); ++// ++// for(i = 1; i < TARGET_NSIG_WORDS; i++) { ++// __put_user(set->sig[i], &frame->extramask[i - 1]); ++// } ++// ++// /* Set up to return from userspace. If provided, use a stub ++// already in userspace. */ ++// if (ka->sa_flags & TARGET_SA_RESTORER) { ++// __put_user(ka->sa_restorer, &frame->pretcode); ++// } else { ++// uint16_t val16; ++// abi_ulong retcode_addr; ++// retcode_addr = frame_addr + offsetof(struct sigframe, retcode); ++// __put_user(retcode_addr, &frame->pretcode); ++// /* This is popl %eax ; movl $,%eax ; int $0x80 */ ++// val16 = 0xb858; ++// __put_user(val16, (uint16_t *)(frame->retcode+0)); ++// __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2)); ++// val16 = 0x80cd; ++// __put_user(val16, (uint16_t *)(frame->retcode+6)); ++// } ++// ++// ++// /* Set up registers for signal handler */ ++// env->regs[R_ESP] = frame_addr; ++// env->eip = ka->_sa_handler; ++// ++// cpu_x86_load_seg(env, R_DS, __USER_DS); ++// cpu_x86_load_seg(env, R_ES, __USER_DS); ++// cpu_x86_load_seg(env, R_SS, __USER_DS); ++// cpu_x86_load_seg(env, R_CS, __USER_CS); ++// env->eflags &= ~TF_MASK; ++// ++// unlock_user_struct(frame, frame_addr, 1); ++// ++// return; ++// ++//give_sigsegv: ++// if (sig == TARGET_SIGSEGV) ++// ka->_sa_handler = TARGET_SIG_DFL; ++// force_sig(TARGET_SIGSEGV /* , current */); ++//} + + /* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */ +-static void setup_rt_frame(int sig, struct target_sigaction *ka, +- target_siginfo_t *info, +- target_sigset_t *set, CPUX86State *env) +-{ +- abi_ulong frame_addr, addr; +- struct rt_sigframe *frame; +- int i; +- +- frame_addr = get_sigframe(ka, env, sizeof(*frame)); +- +- if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) +- goto give_sigsegv; +- +- __put_user(sig, &frame->sig); +- addr = frame_addr + offsetof(struct rt_sigframe, info); +- __put_user(addr, &frame->pinfo); +- addr = frame_addr + offsetof(struct rt_sigframe, uc); +- __put_user(addr, &frame->puc); +- tswap_siginfo(&frame->info, info); +- +- /* Create the ucontext. */ +- __put_user(0, &frame->uc.tuc_flags); +- __put_user(0, &frame->uc.tuc_link); +- __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp); +- __put_user(sas_ss_flags(get_sp_from_cpustate(env)), +- &frame->uc.tuc_stack.ss_flags); +- __put_user(target_sigaltstack_used.ss_size, +- &frame->uc.tuc_stack.ss_size); +- setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, env, +- set->sig[0], frame_addr + offsetof(struct rt_sigframe, fpstate)); +- +- for(i = 0; i < TARGET_NSIG_WORDS; i++) { +- __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]); +- } +- +- /* Set up to return from userspace. If provided, use a stub +- already in userspace. */ +- if (ka->sa_flags & TARGET_SA_RESTORER) { +- __put_user(ka->sa_restorer, &frame->pretcode); +- } else { +- uint16_t val16; +- addr = frame_addr + offsetof(struct rt_sigframe, retcode); +- __put_user(addr, &frame->pretcode); +- /* This is movl $,%eax ; int $0x80 */ +- __put_user(0xb8, (char *)(frame->retcode+0)); +- __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1)); +- val16 = 0x80cd; +- __put_user(val16, (uint16_t *)(frame->retcode+5)); +- } +- +- /* Set up registers for signal handler */ +- env->regs[R_ESP] = frame_addr; +- env->eip = ka->_sa_handler; +- +- cpu_x86_load_seg(env, R_DS, __USER_DS); +- cpu_x86_load_seg(env, R_ES, __USER_DS); +- cpu_x86_load_seg(env, R_SS, __USER_DS); +- cpu_x86_load_seg(env, R_CS, __USER_CS); +- env->eflags &= ~TF_MASK; +- +- unlock_user_struct(frame, frame_addr, 1); +- +- return; +- +-give_sigsegv: +- if (sig == TARGET_SIGSEGV) +- ka->_sa_handler = TARGET_SIG_DFL; +- force_sig(TARGET_SIGSEGV /* , current */); +-} ++//static void setup_rt_frame(int sig, struct target_sigaction *ka, ++// target_siginfo_t *info, ++// target_sigset_t *set, CPUX86State *env) ++//{ ++// abi_ulong frame_addr, addr; ++// struct rt_sigframe *frame; ++// int i; ++// ++// frame_addr = get_sigframe(ka, env, sizeof(*frame)); ++// ++// if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) ++// goto give_sigsegv; ++// ++// __put_user(sig, &frame->sig); ++// addr = frame_addr + offsetof(struct rt_sigframe, info); ++// __put_user(addr, &frame->pinfo); ++// addr = frame_addr + offsetof(struct rt_sigframe, uc); ++// __put_user(addr, &frame->puc); ++// tswap_siginfo(&frame->info, info); ++// ++// /* Create the ucontext. */ ++// __put_user(0, &frame->uc.tuc_flags); ++// __put_user(0, &frame->uc.tuc_link); ++// __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp); ++// __put_user(sas_ss_flags(get_sp_from_cpustate(env)), ++// &frame->uc.tuc_stack.ss_flags); ++// __put_user(target_sigaltstack_used.ss_size, ++// &frame->uc.tuc_stack.ss_size); ++// setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, env, ++// set->sig[0], frame_addr + offsetof(struct rt_sigframe, fpstate)); ++// ++// for(i = 0; i < TARGET_NSIG_WORDS; i++) { ++// __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]); ++// } ++// ++// /* Set up to return from userspace. If provided, use a stub ++// already in userspace. */ ++// if (ka->sa_flags & TARGET_SA_RESTORER) { ++// __put_user(ka->sa_restorer, &frame->pretcode); ++// } else { ++// uint16_t val16; ++// addr = frame_addr + offsetof(struct rt_sigframe, retcode); ++// __put_user(addr, &frame->pretcode); ++// /* This is movl $,%eax ; int $0x80 */ ++// __put_user(0xb8, (char *)(frame->retcode+0)); ++// __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1)); ++// val16 = 0x80cd; ++// __put_user(val16, (uint16_t *)(frame->retcode+5)); ++// } ++// ++// /* Set up registers for signal handler */ ++// env->regs[R_ESP] = frame_addr; ++// env->eip = ka->_sa_handler; ++// ++// cpu_x86_load_seg(env, R_DS, __USER_DS); ++// cpu_x86_load_seg(env, R_ES, __USER_DS); ++// cpu_x86_load_seg(env, R_SS, __USER_DS); ++// cpu_x86_load_seg(env, R_CS, __USER_CS); ++// env->eflags &= ~TF_MASK; ++// ++// unlock_user_struct(frame, frame_addr, 1); ++// ++// return; ++// ++//give_sigsegv: ++// if (sig == TARGET_SIGSEGV) ++// ka->_sa_handler = TARGET_SIG_DFL; ++// force_sig(TARGET_SIGSEGV /* , current */); ++//} + + static int + restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax) +@@ -2445,7 +2487,7 @@ segv_and_exit: + long do_rt_sigreturn(CPUSPARCState *env) + { + fprintf(stderr, "do_rt_sigreturn: not implemented\n"); +- return -TARGET_ENOSYS; ++ return TARGET_ENOSYS; + } + + #if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) +@@ -3024,7 +3066,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, + * + * a0 = signal number + * a1 = pointer to siginfo_t +- * a2 = pointer to struct ucontext ++ * a2 = pointer to ucontext_t + * + * $25 and PC point to the signal handler, $29 points to the + * struct sigframe. +@@ -3417,7 +3459,7 @@ struct target_signal_frame { + + struct rt_signal_frame { + siginfo_t info; +- struct ucontext uc; ++ ucontext_t uc; + uint32_t tramp[2]; + }; + +@@ -3606,7 +3648,7 @@ long do_sigreturn(CPUMBState *env) + long do_rt_sigreturn(CPUMBState *env) + { + fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n"); +- return -TARGET_ENOSYS; ++ return TARGET_ENOSYS; + } + + #elif defined(TARGET_CRIS) +@@ -3628,7 +3670,7 @@ struct rt_signal_frame { + siginfo_t *pinfo; + void *puc; + siginfo_t info; +- struct ucontext uc; ++ ucontext_t uc; + uint16_t retcode[4]; /* Trampoline code. */ + }; + +@@ -3769,7 +3811,7 @@ long do_sigreturn(CPUCRISState *env) + long do_rt_sigreturn(CPUCRISState *env) + { + fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n"); +- return -TARGET_ENOSYS; ++ return TARGET_ENOSYS; + } + + #elif defined(TARGET_OPENRISC) +@@ -3931,7 +3973,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, + tswap_siginfo(&frame->info, info); + } + +- /*err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));*/ ++ /*err |= __clear_user(&frame->uc, offsetof(ucontext_t, uc_mcontext));*/ + __put_user(0, &frame->uc.tuc_flags); + __put_user(0, &frame->uc.tuc_link); + __put_user(target_sigaltstack_used.ss_sp, +@@ -3981,13 +4023,13 @@ long do_sigreturn(CPUOpenRISCState *env) + { + + qemu_log("do_sigreturn: not implemented\n"); +- return -TARGET_ENOSYS; ++ return TARGET_ENOSYS; + } + + long do_rt_sigreturn(CPUOpenRISCState *env) + { + qemu_log("do_rt_sigreturn: not implemented\n"); +- return -TARGET_ENOSYS; ++ return TARGET_ENOSYS; + } + /* TARGET_OPENRISC */ + +@@ -4413,7 +4455,7 @@ enum { + + struct target_ucontext { + target_ulong tuc_flags; +- target_ulong tuc_link; /* struct ucontext __user * */ ++ target_ulong tuc_link; /* ucontext_t __user * */ + struct target_sigaltstack tuc_stack; + #if !defined(TARGET_PPC64) + int32_t tuc_pad[7]; +@@ -5562,13 +5604,13 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka, + long do_sigreturn(CPUArchState *env) + { + fprintf(stderr, "do_sigreturn: not implemented\n"); +- return -TARGET_ENOSYS; ++ return TARGET_ENOSYS; + } + + long do_rt_sigreturn(CPUArchState *env) + { + fprintf(stderr, "do_rt_sigreturn: not implemented\n"); +- return -TARGET_ENOSYS; ++ return TARGET_ENOSYS; + } + + #endif +@@ -5578,8 +5620,8 @@ void process_pending_signals(CPUArchState *cpu_env) + CPUState *cpu = ENV_GET_CPU(cpu_env); + int sig; + abi_ulong handler; +- sigset_t set, old_set; +- target_sigset_t target_old_set; ++ //sigset_t set, old_set; ++ //target_sigset_t target_old_set; + struct emulated_sigtable *k; + struct target_sigaction *sa; + struct sigqueue *q; +@@ -5618,6 +5660,14 @@ void process_pending_signals(CPUArchState *cpu_env) + handler = sa->_sa_handler; + } + ++ if (sig == TARGET_SIGPIPE) { ++ /* SIGPIPE does not exist in CGC-world */ ++#ifdef DEBUG_SIGNAL ++ fprintf(stderr, "qemu: ignoring SIGPIPE\n"); ++#endif ++ handler = TARGET_SIG_IGN; ++ } ++ + if (ts->sigsegv_blocked && sig == TARGET_SIGSEGV) { + /* Guest has blocked SIGSEGV but we got one anyway. Assume this + * is a forced SIGSEGV (ie one the kernel handles via force_sig_info +@@ -5641,39 +5691,29 @@ void process_pending_signals(CPUArchState *cpu_env) + } else if (handler == TARGET_SIG_ERR) { + force_sig(sig); + } else { +- /* compute the blocked signals during the handler execution */ +- target_to_host_sigset(&set, &sa->sa_mask); +- /* SA_NODEFER indicates that the current signal should not be +- blocked during the handler */ +- if (!(sa->sa_flags & TARGET_SA_NODEFER)) +- sigaddset(&set, target_to_host_signal(sig)); +- +- /* block signals in the handler using Linux */ +- do_sigprocmask(SIG_BLOCK, &set, &old_set); +- /* save the previous blocked signal state to restore it at the +- end of the signal execution (see do_sigreturn) */ +- host_to_target_sigset_internal(&target_old_set, &old_set); +- +- /* if the CPU is in VM86 mode, we restore the 32 bit values */ +-#if defined(TARGET_I386) && !defined(TARGET_X86_64) +- { +- CPUX86State *env = cpu_env; +- if (env->eflags & VM_MASK) +- save_v86_state(env); +- } +-#endif +- /* prepare the stack frame of the virtual CPU */ +-#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) +- /* These targets do not have traditional signals. */ +- setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env); +-#else +- if (sa->sa_flags & TARGET_SA_SIGINFO) +- setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env); +- else +- setup_frame(sig, sa, &target_old_set, cpu_env); +-#endif +- if (sa->sa_flags & TARGET_SA_RESETHAND) +- sa->_sa_handler = TARGET_SIG_DFL; ++ fprintf(stderr, "There's a handler for signal %d! It cannot be!", sig); ++ exit(-35); ++// /* compute the blocked signals during the handler execution */ ++// target_to_host_sigset(&set, &sa->sa_mask); ++// /* SA_NODEFER indicates that the current signal should not be ++// blocked during the handler */ ++// if (!(sa->sa_flags & TARGET_SA_NODEFER)) ++// sigaddset(&set, target_to_host_signal(sig)); ++// ++// /* block signals in the handler using Linux */ ++// do_sigprocmask(SIG_BLOCK, &set, &old_set); ++// /* save the previous blocked signal state to restore it at the ++// end of the signal execution (see do_sigreturn) */ ++// host_to_target_sigset_internal(&target_old_set, &old_set); ++// ++// /* prepare the stack frame of the virtual CPU */ ++// if (sa->sa_flags & TARGET_SA_SIGINFO) ++// setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env); ++// else ++// setup_frame(sig, sa, &target_old_set, cpu_env); ++// ++// if (sa->sa_flags & TARGET_SA_RESETHAND) ++// sa->_sa_handler = TARGET_SIG_DFL; + } + if (q != &k->info) + free_sigqueue(cpu_env, q); +diff --git a/home/gkrishna/Shelly/work/qemu/linux-user/strace.c b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/strace.c +index ea6c1d2..583fcca 100644 +--- a/home/gkrishna/Shelly/work/qemu/linux-user/strace.c ++++ b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/strace.c +@@ -13,143 +13,7 @@ + + int do_strace=0; + +-struct syscallname { +- int nr; +- const char *name; +- const char *format; +- void (*call)(const struct syscallname *, +- abi_long, abi_long, abi_long, +- abi_long, abi_long, abi_long); +- void (*result)(const struct syscallname *, abi_long); +-}; + +-#ifdef __GNUC__ +-/* +- * It is possible that target doesn't have syscall that uses +- * following flags but we don't want the compiler to warn +- * us about them being unused. Same applies to utility print +- * functions. It is ok to keep them while not used. +- */ +-#define UNUSED __attribute__ ((unused)) +-#else +-#define UNUSED +-#endif +- +-/* +- * Structure used to translate flag values into strings. This is +- * similar that is in the actual strace tool. +- */ +-struct flags { +- abi_long f_value; /* flag */ +- const char *f_string; /* stringified flag */ +-}; +- +-/* common flags for all architectures */ +-#define FLAG_GENERIC(name) { name, #name } +-/* target specific flags (syscall_defs.h has TARGET_) */ +-#define FLAG_TARGET(name) { TARGET_ ## name, #name } +-/* end of flags array */ +-#define FLAG_END { 0, NULL } +- +-UNUSED static const char *get_comma(int); +-UNUSED static void print_pointer(abi_long, int); +-UNUSED static void print_flags(const struct flags *, abi_long, int); +-UNUSED static void print_at_dirfd(abi_long, int); +-UNUSED static void print_file_mode(abi_long, int); +-UNUSED static void print_open_flags(abi_long, int); +-UNUSED static void print_syscall_prologue(const struct syscallname *); +-UNUSED static void print_syscall_epilogue(const struct syscallname *); +-UNUSED static void print_string(abi_long, int); +-UNUSED static void print_raw_param(const char *, abi_long, int); +-UNUSED static void print_timeval(abi_ulong, int); +-UNUSED static void print_number(abi_long, int); +-UNUSED static void print_signal(abi_ulong, int); +- +-/* +- * Utility functions +- */ +-static void +-print_ipc_cmd(int cmd) +-{ +-#define output_cmd(val) \ +-if( cmd == val ) { \ +- gemu_log(#val); \ +- return; \ +-} +- +- cmd &= 0xff; +- +- /* General IPC commands */ +- output_cmd( IPC_RMID ); +- output_cmd( IPC_SET ); +- output_cmd( IPC_STAT ); +- output_cmd( IPC_INFO ); +- /* msgctl() commands */ +- #ifdef __USER_MISC +- output_cmd( MSG_STAT ); +- output_cmd( MSG_INFO ); +- #endif +- /* shmctl() commands */ +- output_cmd( SHM_LOCK ); +- output_cmd( SHM_UNLOCK ); +- output_cmd( SHM_STAT ); +- output_cmd( SHM_INFO ); +- /* semctl() commands */ +- output_cmd( GETPID ); +- output_cmd( GETVAL ); +- output_cmd( GETALL ); +- output_cmd( GETNCNT ); +- output_cmd( GETZCNT ); +- output_cmd( SETVAL ); +- output_cmd( SETALL ); +- output_cmd( SEM_STAT ); +- output_cmd( SEM_INFO ); +- output_cmd( IPC_RMID ); +- output_cmd( IPC_RMID ); +- output_cmd( IPC_RMID ); +- output_cmd( IPC_RMID ); +- output_cmd( IPC_RMID ); +- output_cmd( IPC_RMID ); +- output_cmd( IPC_RMID ); +- output_cmd( IPC_RMID ); +- output_cmd( IPC_RMID ); +- +- /* Some value we don't recognize */ +- gemu_log("%d",cmd); +-} +- +-static void +-print_signal(abi_ulong arg, int last) +-{ +- const char *signal_name = NULL; +- switch(arg) { +- case TARGET_SIGHUP: signal_name = "SIGHUP"; break; +- case TARGET_SIGINT: signal_name = "SIGINT"; break; +- case TARGET_SIGQUIT: signal_name = "SIGQUIT"; break; +- case TARGET_SIGILL: signal_name = "SIGILL"; break; +- case TARGET_SIGABRT: signal_name = "SIGABRT"; break; +- case TARGET_SIGFPE: signal_name = "SIGFPE"; break; +- case TARGET_SIGKILL: signal_name = "SIGKILL"; break; +- case TARGET_SIGSEGV: signal_name = "SIGSEGV"; break; +- case TARGET_SIGPIPE: signal_name = "SIGPIPE"; break; +- case TARGET_SIGALRM: signal_name = "SIGALRM"; break; +- case TARGET_SIGTERM: signal_name = "SIGTERM"; break; +- case TARGET_SIGUSR1: signal_name = "SIGUSR1"; break; +- case TARGET_SIGUSR2: signal_name = "SIGUSR2"; break; +- case TARGET_SIGCHLD: signal_name = "SIGCHLD"; break; +- case TARGET_SIGCONT: signal_name = "SIGCONT"; break; +- case TARGET_SIGSTOP: signal_name = "SIGSTOP"; break; +- case TARGET_SIGTTIN: signal_name = "SIGTTIN"; break; +- case TARGET_SIGTTOU: signal_name = "SIGTTOU"; break; +- } +- if (signal_name == NULL) { +- print_raw_param("%ld", arg, last); +- return; +- } +- gemu_log("%s%s", signal_name, get_comma(last)); +-} +- +-#ifdef TARGET_NR__newselect + static void + print_fdset(int n, abi_ulong target_fds_addr) + { +@@ -175,330 +39,7 @@ print_fdset(int n, abi_ulong target_fds_addr) + } + gemu_log("]"); + } +-#endif +- +-/* +- * Sysycall specific output functions +- */ +- +-/* select */ +-#ifdef TARGET_NR__newselect +-static long newselect_arg1 = 0; +-static long newselect_arg2 = 0; +-static long newselect_arg3 = 0; +-static long newselect_arg4 = 0; +-static long newselect_arg5 = 0; +- +-static void +-print_newselect(const struct syscallname *name, +- abi_long arg1, abi_long arg2, abi_long arg3, +- abi_long arg4, abi_long arg5, abi_long arg6) +-{ +- gemu_log("%s(" TARGET_ABI_FMT_ld ",", name->name, arg1); +- print_fdset(arg1, arg2); +- gemu_log(","); +- print_fdset(arg1, arg3); +- gemu_log(","); +- print_fdset(arg1, arg4); +- gemu_log(","); +- print_timeval(arg5, 1); +- gemu_log(")"); +- +- /* save for use in the return output function below */ +- newselect_arg1=arg1; +- newselect_arg2=arg2; +- newselect_arg3=arg3; +- newselect_arg4=arg4; +- newselect_arg5=arg5; +-} +-#endif +- +-#ifdef TARGET_NR_semctl +-static void +-print_semctl(const struct syscallname *name, +- abi_long arg1, abi_long arg2, abi_long arg3, +- abi_long arg4, abi_long arg5, abi_long arg6) +-{ +- gemu_log("%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ",", name->name, arg1, arg2); +- print_ipc_cmd(arg3); +- gemu_log(",0x" TARGET_ABI_FMT_lx ")", arg4); +-} +-#endif +- +-static void +-print_execve(const struct syscallname *name, +- abi_long arg1, abi_long arg2, abi_long arg3, +- abi_long arg4, abi_long arg5, abi_long arg6) +-{ +- abi_ulong arg_ptr_addr; +- char *s; +- +- if (!(s = lock_user_string(arg1))) +- return; +- gemu_log("%s(\"%s\",{", name->name, s); +- unlock_user(s, arg1, 0); +- +- for (arg_ptr_addr = arg2; ; arg_ptr_addr += sizeof(abi_ulong)) { +- abi_ulong *arg_ptr, arg_addr; +- +- arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(abi_ulong), 1); +- if (!arg_ptr) +- return; +- arg_addr = tswapal(*arg_ptr); +- unlock_user(arg_ptr, arg_ptr_addr, 0); +- if (!arg_addr) +- break; +- if ((s = lock_user_string(arg_addr))) { +- gemu_log("\"%s\",", s); +- unlock_user(s, arg_addr, 0); +- } +- } +- +- gemu_log("NULL})"); +-} +- +-#ifdef TARGET_NR_ipc +-static void +-print_ipc(const struct syscallname *name, +- abi_long arg1, abi_long arg2, abi_long arg3, +- abi_long arg4, abi_long arg5, abi_long arg6) +-{ +- switch(arg1) { +- case IPCOP_semctl: +- gemu_log("semctl(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ",", arg1, arg2); +- print_ipc_cmd(arg3); +- gemu_log(",0x" TARGET_ABI_FMT_lx ")", arg4); +- break; +- default: +- gemu_log("%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ")", +- name->name, arg1, arg2, arg3, arg4); +- } +-} +-#endif +- +-/* +- * Variants for the return value output function +- */ +- +-static void +-print_syscall_ret_addr(const struct syscallname *name, abi_long ret) +-{ +- char *errstr = NULL; +- +- if (ret < 0) { +- errstr = target_strerror(-ret); +- } +- if (errstr) { +- gemu_log(" = -1 errno=%d (%s)\n", (int)-ret, errstr); +- } else { +- gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret); +- } +-} +- +-#if 0 /* currently unused */ +-static void +-print_syscall_ret_raw(struct syscallname *name, abi_long ret) +-{ +- gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret); +-} +-#endif +- +-#ifdef TARGET_NR__newselect +-static void +-print_syscall_ret_newselect(const struct syscallname *name, abi_long ret) +-{ +- gemu_log(" = 0x" TARGET_ABI_FMT_lx " (", ret); +- print_fdset(newselect_arg1,newselect_arg2); +- gemu_log(","); +- print_fdset(newselect_arg1,newselect_arg3); +- gemu_log(","); +- print_fdset(newselect_arg1,newselect_arg4); +- gemu_log(","); +- print_timeval(newselect_arg5, 1); +- gemu_log(")\n"); +-} +-#endif +- +-UNUSED static struct flags access_flags[] = { +- FLAG_GENERIC(F_OK), +- FLAG_GENERIC(R_OK), +- FLAG_GENERIC(W_OK), +- FLAG_GENERIC(X_OK), +- FLAG_END, +-}; +- +-UNUSED static struct flags at_file_flags[] = { +-#ifdef AT_EACCESS +- FLAG_GENERIC(AT_EACCESS), +-#endif +-#ifdef AT_SYMLINK_NOFOLLOW +- FLAG_GENERIC(AT_SYMLINK_NOFOLLOW), +-#endif +- FLAG_END, +-}; + +-UNUSED static struct flags unlinkat_flags[] = { +-#ifdef AT_REMOVEDIR +- FLAG_GENERIC(AT_REMOVEDIR), +-#endif +- FLAG_END, +-}; +- +-UNUSED static struct flags mode_flags[] = { +- FLAG_GENERIC(S_IFSOCK), +- FLAG_GENERIC(S_IFLNK), +- FLAG_GENERIC(S_IFREG), +- FLAG_GENERIC(S_IFBLK), +- FLAG_GENERIC(S_IFDIR), +- FLAG_GENERIC(S_IFCHR), +- FLAG_GENERIC(S_IFIFO), +- FLAG_END, +-}; +- +-UNUSED static struct flags open_access_flags[] = { +- FLAG_TARGET(O_RDONLY), +- FLAG_TARGET(O_WRONLY), +- FLAG_TARGET(O_RDWR), +- FLAG_END, +-}; +- +-UNUSED static struct flags open_flags[] = { +- FLAG_TARGET(O_APPEND), +- FLAG_TARGET(O_CREAT), +- FLAG_TARGET(O_DIRECTORY), +- FLAG_TARGET(O_EXCL), +- FLAG_TARGET(O_LARGEFILE), +- FLAG_TARGET(O_NOCTTY), +- FLAG_TARGET(O_NOFOLLOW), +- FLAG_TARGET(O_NONBLOCK), /* also O_NDELAY */ +- FLAG_TARGET(O_DSYNC), +- FLAG_TARGET(__O_SYNC), +- FLAG_TARGET(O_TRUNC), +-#ifdef O_DIRECT +- FLAG_TARGET(O_DIRECT), +-#endif +-#ifdef O_NOATIME +- FLAG_TARGET(O_NOATIME), +-#endif +-#ifdef O_CLOEXEC +- FLAG_TARGET(O_CLOEXEC), +-#endif +-#ifdef O_PATH +- FLAG_TARGET(O_PATH), +-#endif +- FLAG_END, +-}; +- +-UNUSED static struct flags mount_flags[] = { +-#ifdef MS_BIND +- FLAG_GENERIC(MS_BIND), +-#endif +-#ifdef MS_DIRSYNC +- FLAG_GENERIC(MS_DIRSYNC), +-#endif +- FLAG_GENERIC(MS_MANDLOCK), +-#ifdef MS_MOVE +- FLAG_GENERIC(MS_MOVE), +-#endif +- FLAG_GENERIC(MS_NOATIME), +- FLAG_GENERIC(MS_NODEV), +- FLAG_GENERIC(MS_NODIRATIME), +- FLAG_GENERIC(MS_NOEXEC), +- FLAG_GENERIC(MS_NOSUID), +- FLAG_GENERIC(MS_RDONLY), +-#ifdef MS_RELATIME +- FLAG_GENERIC(MS_RELATIME), +-#endif +- FLAG_GENERIC(MS_REMOUNT), +- FLAG_GENERIC(MS_SYNCHRONOUS), +- FLAG_END, +-}; +- +-UNUSED static struct flags umount2_flags[] = { +-#ifdef MNT_FORCE +- FLAG_GENERIC(MNT_FORCE), +-#endif +-#ifdef MNT_DETACH +- FLAG_GENERIC(MNT_DETACH), +-#endif +-#ifdef MNT_EXPIRE +- FLAG_GENERIC(MNT_EXPIRE), +-#endif +- FLAG_END, +-}; +- +-UNUSED static struct flags mmap_prot_flags[] = { +- FLAG_GENERIC(PROT_NONE), +- FLAG_GENERIC(PROT_EXEC), +- FLAG_GENERIC(PROT_READ), +- FLAG_GENERIC(PROT_WRITE), +- FLAG_TARGET(PROT_SEM), +- FLAG_GENERIC(PROT_GROWSDOWN), +- FLAG_GENERIC(PROT_GROWSUP), +- FLAG_END, +-}; +- +-UNUSED static struct flags mmap_flags[] = { +- FLAG_TARGET(MAP_SHARED), +- FLAG_TARGET(MAP_PRIVATE), +- FLAG_TARGET(MAP_ANONYMOUS), +- FLAG_TARGET(MAP_DENYWRITE), +- FLAG_TARGET(MAP_FIXED), +- FLAG_TARGET(MAP_GROWSDOWN), +- FLAG_TARGET(MAP_EXECUTABLE), +-#ifdef MAP_LOCKED +- FLAG_TARGET(MAP_LOCKED), +-#endif +-#ifdef MAP_NONBLOCK +- FLAG_TARGET(MAP_NONBLOCK), +-#endif +- FLAG_TARGET(MAP_NORESERVE), +-#ifdef MAP_POPULATE +- FLAG_TARGET(MAP_POPULATE), +-#endif +-#ifdef TARGET_MAP_UNINITIALIZED +- FLAG_TARGET(MAP_UNINITIALIZED), +-#endif +- FLAG_END, +-}; +- +-UNUSED static struct flags clone_flags[] = { +- FLAG_GENERIC(CLONE_VM), +- FLAG_GENERIC(CLONE_FS), +- FLAG_GENERIC(CLONE_FILES), +- FLAG_GENERIC(CLONE_SIGHAND), +- FLAG_GENERIC(CLONE_PTRACE), +- FLAG_GENERIC(CLONE_VFORK), +- FLAG_GENERIC(CLONE_PARENT), +- FLAG_GENERIC(CLONE_THREAD), +- FLAG_GENERIC(CLONE_NEWNS), +- FLAG_GENERIC(CLONE_SYSVSEM), +- FLAG_GENERIC(CLONE_SETTLS), +- FLAG_GENERIC(CLONE_PARENT_SETTID), +- FLAG_GENERIC(CLONE_CHILD_CLEARTID), +- FLAG_GENERIC(CLONE_DETACHED), +- FLAG_GENERIC(CLONE_UNTRACED), +- FLAG_GENERIC(CLONE_CHILD_SETTID), +-#if defined(CLONE_NEWUTS) +- FLAG_GENERIC(CLONE_NEWUTS), +-#endif +-#if defined(CLONE_NEWIPC) +- FLAG_GENERIC(CLONE_NEWIPC), +-#endif +-#if defined(CLONE_NEWUSER) +- FLAG_GENERIC(CLONE_NEWUSER), +-#endif +-#if defined(CLONE_NEWPID) +- FLAG_GENERIC(CLONE_NEWPID), +-#endif +-#if defined(CLONE_NEWNET) +- FLAG_GENERIC(CLONE_NEWNET), +-#endif +-#if defined(CLONE_IO) +- FLAG_GENERIC(CLONE_IO), +-#endif +- FLAG_END, +-}; + + /* + * print_xxx utility functions. These are used to print syscall +@@ -510,115 +51,7 @@ UNUSED static struct flags clone_flags[] = { + static const char * + get_comma(int last) + { +- return ((last) ? "" : ","); +-} +- +-static void +-print_flags(const struct flags *f, abi_long flags, int last) +-{ +- const char *sep = ""; +- int n; +- +- if ((flags == 0) && (f->f_value == 0)) { +- gemu_log("%s%s", f->f_string, get_comma(last)); +- return; +- } +- for (n = 0; f->f_string != NULL; f++) { +- if ((f->f_value != 0) && ((flags & f->f_value) == f->f_value)) { +- gemu_log("%s%s", sep, f->f_string); +- flags &= ~f->f_value; +- sep = "|"; +- n++; +- } +- } +- +- if (n > 0) { +- /* print rest of the flags as numeric */ +- if (flags != 0) { +- gemu_log("%s%#x%s", sep, (unsigned int)flags, get_comma(last)); +- } else { +- gemu_log("%s", get_comma(last)); +- } +- } else { +- /* no string version of flags found, print them in hex then */ +- gemu_log("%#x%s", (unsigned int)flags, get_comma(last)); +- } +-} +- +-static void +-print_at_dirfd(abi_long dirfd, int last) +-{ +-#ifdef AT_FDCWD +- if (dirfd == AT_FDCWD) { +- gemu_log("AT_FDCWD%s", get_comma(last)); +- return; +- } +-#endif +- gemu_log("%d%s", (int)dirfd, get_comma(last)); +-} +- +-static void +-print_file_mode(abi_long mode, int last) +-{ +- const char *sep = ""; +- const struct flags *m; +- +- for (m = &mode_flags[0]; m->f_string != NULL; m++) { +- if ((m->f_value & mode) == m->f_value) { +- gemu_log("%s%s", m->f_string, sep); +- sep = "|"; +- mode &= ~m->f_value; +- break; +- } +- } +- +- mode &= ~S_IFMT; +- /* print rest of the mode as octal */ +- if (mode != 0) +- gemu_log("%s%#o", sep, (unsigned int)mode); +- +- gemu_log("%s", get_comma(last)); +-} +- +-static void +-print_open_flags(abi_long flags, int last) +-{ +- print_flags(open_access_flags, flags & TARGET_O_ACCMODE, 1); +- flags &= ~TARGET_O_ACCMODE; +- if (flags == 0) { +- gemu_log("%s", get_comma(last)); +- return; +- } +- gemu_log("|"); +- print_flags(open_flags, flags, last); +-} +- +-static void +-print_syscall_prologue(const struct syscallname *sc) +-{ +- gemu_log("%s(", sc->name); +-} +- +-/*ARGSUSED*/ +-static void +-print_syscall_epilogue(const struct syscallname *sc) +-{ +- (void)sc; +- gemu_log(")"); +-} +- +-static void +-print_string(abi_long addr, int last) +-{ +- char *s; +- +- if ((s = lock_user_string(addr)) != NULL) { +- gemu_log("\"%s\"%s", s, get_comma(last)); +- unlock_user(s, addr, 0); +- } else { +- /* can't get string out of it, so print it as pointer */ +- print_pointer(addr, last); +- } ++ return ((last) ? "" : ", "); + } + + /* +@@ -643,23 +76,6 @@ print_pointer(abi_long p, int last) + gemu_log("0x" TARGET_ABI_FMT_lx "%s", p, get_comma(last)); + } + +-/* +- * Reads 32-bit (int) number from guest address space from +- * address 'addr' and prints it. +- */ +-static void +-print_number(abi_long addr, int last) +-{ +- if (addr == 0) { +- gemu_log("NULL%s", get_comma(last)); +- } else { +- int num; +- +- get_user_s32(num, addr); +- gemu_log("[%d]%s", num, get_comma(last)); +- } +-} +- + static void + print_timeval(abi_ulong tv_addr, int last) + { +@@ -676,891 +92,6 @@ print_timeval(abi_ulong tv_addr, int last) + gemu_log("NULL%s", get_comma(last)); + } + +-#undef UNUSED +- +-#ifdef TARGET_NR_accept +-static void +-print_accept(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_raw_param("%d", arg0, 0); +- print_pointer(arg1, 0); +- print_number(arg2, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_access +-static void +-print_access(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_string(arg0, 0); +- print_flags(access_flags, arg1, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_brk +-static void +-print_brk(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_pointer(arg0, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_chdir +-static void +-print_chdir(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_string(arg0, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_chmod +-static void +-print_chmod(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_string(arg0, 0); +- print_file_mode(arg1, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_clone +-static void +-print_clone(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +-#if defined(TARGET_M68K) +- print_flags(clone_flags, arg0, 0); +- print_raw_param("newsp=0x" TARGET_ABI_FMT_lx, arg1, 1); +-#elif defined(TARGET_SH4) || defined(TARGET_ALPHA) +- print_flags(clone_flags, arg0, 0); +- print_raw_param("child_stack=0x" TARGET_ABI_FMT_lx, arg1, 0); +- print_raw_param("parent_tidptr=0x" TARGET_ABI_FMT_lx, arg2, 0); +- print_raw_param("child_tidptr=0x" TARGET_ABI_FMT_lx, arg3, 0); +- print_raw_param("tls=0x" TARGET_ABI_FMT_lx, arg4, 1); +-#elif defined(TARGET_CRIS) +- print_raw_param("child_stack=0x" TARGET_ABI_FMT_lx, arg0, 0); +- print_flags(clone_flags, arg1, 0); +- print_raw_param("parent_tidptr=0x" TARGET_ABI_FMT_lx, arg2, 0); +- print_raw_param("tls=0x" TARGET_ABI_FMT_lx, arg3, 0); +- print_raw_param("child_tidptr=0x" TARGET_ABI_FMT_lx, arg4, 1); +-#else +- print_flags(clone_flags, arg0, 0); +- print_raw_param("child_stack=0x" TARGET_ABI_FMT_lx, arg1, 0); +- print_raw_param("parent_tidptr=0x" TARGET_ABI_FMT_lx, arg2, 0); +- print_raw_param("tls=0x" TARGET_ABI_FMT_lx, arg3, 0); +- print_raw_param("child_tidptr=0x" TARGET_ABI_FMT_lx, arg4, 1); +-#endif +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_creat +-static void +-print_creat(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_string(arg0, 0); +- print_file_mode(arg1, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_execv +-static void +-print_execv(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_string(arg0, 0); +- print_raw_param("0x" TARGET_ABI_FMT_lx, arg1, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_faccessat +-static void +-print_faccessat(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_at_dirfd(arg0, 0); +- print_string(arg1, 0); +- print_flags(access_flags, arg2, 0); +- print_flags(at_file_flags, arg3, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_fchmodat +-static void +-print_fchmodat(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_at_dirfd(arg0, 0); +- print_string(arg1, 0); +- print_file_mode(arg2, 0); +- print_flags(at_file_flags, arg3, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_fchownat +-static void +-print_fchownat(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_at_dirfd(arg0, 0); +- print_string(arg1, 0); +- print_raw_param("%d", arg2, 0); +- print_raw_param("%d", arg3, 0); +- print_flags(at_file_flags, arg4, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#if defined(TARGET_NR_fcntl) || defined(TARGET_NR_fcntl64) +-static void +-print_fcntl(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_raw_param("%d", arg0, 0); +- switch(arg1) { +- case TARGET_F_DUPFD: +- gemu_log("F_DUPFD,"); +- print_raw_param(TARGET_ABI_FMT_ld, arg2, 1); +- break; +- case TARGET_F_GETFD: +- gemu_log("F_GETFD"); +- break; +- case TARGET_F_SETFD: +- gemu_log("F_SETFD,"); +- print_raw_param(TARGET_ABI_FMT_ld, arg2, 1); +- break; +- case TARGET_F_GETFL: +- gemu_log("F_GETFL"); +- break; +- case TARGET_F_SETFL: +- gemu_log("F_SETFL,"); +- print_open_flags(arg2, 1); +- break; +- case TARGET_F_GETLK: +- gemu_log("F_GETLK,"); +- print_pointer(arg2, 1); +- break; +- case TARGET_F_SETLK: +- gemu_log("F_SETLK,"); +- print_pointer(arg2, 1); +- break; +- case TARGET_F_SETLKW: +- gemu_log("F_SETLKW,"); +- print_pointer(arg2, 1); +- break; +- case TARGET_F_GETOWN: +- gemu_log("F_GETOWN"); +- break; +- case TARGET_F_SETOWN: +- gemu_log("F_SETOWN,"); +- print_raw_param(TARGET_ABI_FMT_ld, arg2, 0); +- break; +- case TARGET_F_GETSIG: +- gemu_log("F_GETSIG"); +- break; +- case TARGET_F_SETSIG: +- gemu_log("F_SETSIG,"); +- print_raw_param(TARGET_ABI_FMT_ld, arg2, 0); +- break; +-#if TARGET_ABI_BITS == 32 +- case TARGET_F_GETLK64: +- gemu_log("F_GETLK64,"); +- print_pointer(arg2, 1); +- break; +- case TARGET_F_SETLK64: +- gemu_log("F_SETLK64,"); +- print_pointer(arg2, 1); +- break; +- case TARGET_F_SETLKW64: +- gemu_log("F_SETLKW64,"); +- print_pointer(arg2, 1); +- break; +-#endif +- case TARGET_F_SETLEASE: +- gemu_log("F_SETLEASE,"); +- print_raw_param(TARGET_ABI_FMT_ld, arg2, 0); +- break; +- case TARGET_F_GETLEASE: +- gemu_log("F_GETLEASE"); +- break; +- case TARGET_F_DUPFD_CLOEXEC: +- gemu_log("F_DUPFD_CLOEXEC,"); +- print_raw_param(TARGET_ABI_FMT_ld, arg2, 1); +- break; +- case TARGET_F_NOTIFY: +- gemu_log("F_NOTIFY,"); +- print_raw_param(TARGET_ABI_FMT_ld, arg2, 0); +- break; +- default: +- print_raw_param(TARGET_ABI_FMT_ld, arg1, 0); +- print_pointer(arg2, 1); +- break; +- } +- print_syscall_epilogue(name); +-} +-#define print_fcntl64 print_fcntl +-#endif +- +- +-#ifdef TARGET_NR_futimesat +-static void +-print_futimesat(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_at_dirfd(arg0, 0); +- print_string(arg1, 0); +- print_timeval(arg2, 0); +- print_timeval(arg2 + sizeof (struct target_timeval), 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_link +-static void +-print_link(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_string(arg0, 0); +- print_string(arg1, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_linkat +-static void +-print_linkat(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_at_dirfd(arg0, 0); +- print_string(arg1, 0); +- print_at_dirfd(arg2, 0); +- print_string(arg3, 0); +- print_flags(at_file_flags, arg4, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR__llseek +-static void +-print__llseek(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- const char *whence = "UNKNOWN"; +- print_syscall_prologue(name); +- print_raw_param("%d", arg0, 0); +- print_raw_param("%ld", arg1, 0); +- print_raw_param("%ld", arg2, 0); +- print_pointer(arg3, 0); +- switch(arg4) { +- case SEEK_SET: whence = "SEEK_SET"; break; +- case SEEK_CUR: whence = "SEEK_CUR"; break; +- case SEEK_END: whence = "SEEK_END"; break; +- } +- gemu_log("%s",whence); +- print_syscall_epilogue(name); +-} +-#endif +- +-#if defined(TARGET_NR_stat) || defined(TARGET_NR_stat64) || \ +- defined(TARGET_NR_lstat) || defined(TARGET_NR_lstat64) +-static void +-print_stat(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_string(arg0, 0); +- print_pointer(arg1, 1); +- print_syscall_epilogue(name); +-} +-#define print_lstat print_stat +-#define print_stat64 print_stat +-#define print_lstat64 print_stat +-#endif +- +-#if defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64) +-static void +-print_fstat(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_raw_param("%d", arg0, 0); +- print_pointer(arg1, 1); +- print_syscall_epilogue(name); +-} +-#define print_fstat64 print_fstat +-#endif +- +-#ifdef TARGET_NR_mkdir +-static void +-print_mkdir(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_string(arg0, 0); +- print_file_mode(arg1, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_mkdirat +-static void +-print_mkdirat(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_at_dirfd(arg0, 0); +- print_string(arg1, 0); +- print_file_mode(arg2, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_rmdir +-static void +-print_rmdir(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_string(arg0, 0); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_rt_sigaction +-static void +-print_rt_sigaction(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_signal(arg0, 0); +- print_pointer(arg1, 0); +- print_pointer(arg2, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_rt_sigprocmask +-static void +-print_rt_sigprocmask(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- const char *how = "UNKNOWN"; +- print_syscall_prologue(name); +- switch(arg0) { +- case TARGET_SIG_BLOCK: how = "SIG_BLOCK"; break; +- case TARGET_SIG_UNBLOCK: how = "SIG_UNBLOCK"; break; +- case TARGET_SIG_SETMASK: how = "SIG_SETMASK"; break; +- } +- gemu_log("%s,",how); +- print_pointer(arg1, 0); +- print_pointer(arg2, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_mknod +-static void +-print_mknod(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- int hasdev = (arg1 & (S_IFCHR|S_IFBLK)); +- +- print_syscall_prologue(name); +- print_string(arg0, 0); +- print_file_mode(arg1, (hasdev == 0)); +- if (hasdev) { +- print_raw_param("makedev(%d", major(arg2), 0); +- print_raw_param("%d)", minor(arg2), 1); +- } +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_mknodat +-static void +-print_mknodat(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- int hasdev = (arg2 & (S_IFCHR|S_IFBLK)); +- +- print_syscall_prologue(name); +- print_at_dirfd(arg0, 0); +- print_string(arg1, 0); +- print_file_mode(arg2, (hasdev == 0)); +- if (hasdev) { +- print_raw_param("makedev(%d", major(arg3), 0); +- print_raw_param("%d)", minor(arg3), 1); +- } +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_mq_open +-static void +-print_mq_open(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- int is_creat = (arg1 & TARGET_O_CREAT); +- +- print_syscall_prologue(name); +- print_string(arg0, 0); +- print_open_flags(arg1, (is_creat == 0)); +- if (is_creat) { +- print_file_mode(arg2, 0); +- print_pointer(arg3, 1); +- } +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_open +-static void +-print_open(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- int is_creat = (arg1 & TARGET_O_CREAT); +- +- print_syscall_prologue(name); +- print_string(arg0, 0); +- print_open_flags(arg1, (is_creat == 0)); +- if (is_creat) +- print_file_mode(arg2, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_openat +-static void +-print_openat(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- int is_creat = (arg2 & TARGET_O_CREAT); +- +- print_syscall_prologue(name); +- print_at_dirfd(arg0, 0); +- print_string(arg1, 0); +- print_open_flags(arg2, (is_creat == 0)); +- if (is_creat) +- print_file_mode(arg3, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_mq_unlink +-static void +-print_mq_unlink(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_string(arg0, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#if defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat) +-static void +-print_fstatat64(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_at_dirfd(arg0, 0); +- print_string(arg1, 0); +- print_pointer(arg2, 0); +- print_flags(at_file_flags, arg3, 1); +- print_syscall_epilogue(name); +-} +-#define print_newfstatat print_fstatat64 +-#endif +- +-#ifdef TARGET_NR_readlink +-static void +-print_readlink(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_string(arg0, 0); +- print_pointer(arg1, 0); +- print_raw_param("%u", arg2, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_readlinkat +-static void +-print_readlinkat(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_at_dirfd(arg0, 0); +- print_string(arg1, 0); +- print_pointer(arg2, 0); +- print_raw_param("%u", arg3, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_rename +-static void +-print_rename(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_string(arg0, 0); +- print_string(arg1, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_renameat +-static void +-print_renameat(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_at_dirfd(arg0, 0); +- print_string(arg1, 0); +- print_at_dirfd(arg2, 0); +- print_string(arg3, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_statfs +-static void +-print_statfs(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_string(arg0, 0); +- print_pointer(arg1, 1); +- print_syscall_epilogue(name); +-} +-#define print_statfs64 print_statfs +-#endif +- +-#ifdef TARGET_NR_symlink +-static void +-print_symlink(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_string(arg0, 0); +- print_string(arg1, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_symlinkat +-static void +-print_symlinkat(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_string(arg0, 0); +- print_at_dirfd(arg1, 0); +- print_string(arg2, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_mount +-static void +-print_mount(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_string(arg0, 0); +- print_string(arg1, 0); +- print_string(arg2, 0); +- print_flags(mount_flags, arg3, 0); +- print_pointer(arg4, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_umount +-static void +-print_umount(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_string(arg0, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_umount2 +-static void +-print_umount2(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_string(arg0, 0); +- print_flags(umount2_flags, arg1, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_unlink +-static void +-print_unlink(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_string(arg0, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_unlinkat +-static void +-print_unlinkat(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_at_dirfd(arg0, 0); +- print_string(arg1, 0); +- print_flags(unlinkat_flags, arg2, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_utime +-static void +-print_utime(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_string(arg0, 0); +- print_pointer(arg1, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_utimes +-static void +-print_utimes(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_string(arg0, 0); +- print_pointer(arg1, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_utimensat +-static void +-print_utimensat(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_at_dirfd(arg0, 0); +- print_string(arg1, 0); +- print_pointer(arg2, 0); +- print_flags(at_file_flags, arg3, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#if defined(TARGET_NR_mmap) || defined(TARGET_NR_mmap2) +-static void +-print_mmap(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_pointer(arg0, 0); +- print_raw_param("%d", arg1, 0); +- print_flags(mmap_prot_flags, arg2, 0); +- print_flags(mmap_flags, arg3, 0); +- print_raw_param("%d", arg4, 0); +- print_raw_param("%#x", arg5, 1); +- print_syscall_epilogue(name); +-} +-#define print_mmap2 print_mmap +-#endif +- +-#ifdef TARGET_NR_mprotect +-static void +-print_mprotect(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_pointer(arg0, 0); +- print_raw_param("%d", arg1, 0); +- print_flags(mmap_prot_flags, arg2, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_munmap +-static void +-print_munmap(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_pointer(arg0, 0); +- print_raw_param("%d", arg1, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_futex +-static void print_futex_op(abi_long tflag, int last) +-{ +-#define print_op(val) \ +-if( cmd == val ) { \ +- gemu_log(#val); \ +- return; \ +-} +- +- int cmd = (int)tflag; +-#ifdef FUTEX_PRIVATE_FLAG +- if (cmd & FUTEX_PRIVATE_FLAG) { +- gemu_log("FUTEX_PRIVATE_FLAG|"); +- cmd &= ~FUTEX_PRIVATE_FLAG; +- } +-#endif +-#ifdef FUTEX_CLOCK_REALTIME +- if (cmd & FUTEX_CLOCK_REALTIME) { +- gemu_log("FUTEX_CLOCK_REALTIME|"); +- cmd &= ~FUTEX_CLOCK_REALTIME; +- } +-#endif +- print_op(FUTEX_WAIT) +- print_op(FUTEX_WAKE) +- print_op(FUTEX_FD) +- print_op(FUTEX_REQUEUE) +- print_op(FUTEX_CMP_REQUEUE) +- print_op(FUTEX_WAKE_OP) +- print_op(FUTEX_LOCK_PI) +- print_op(FUTEX_UNLOCK_PI) +- print_op(FUTEX_TRYLOCK_PI) +-#ifdef FUTEX_WAIT_BITSET +- print_op(FUTEX_WAIT_BITSET) +-#endif +-#ifdef FUTEX_WAKE_BITSET +- print_op(FUTEX_WAKE_BITSET) +-#endif +- /* unknown values */ +- gemu_log("%d",cmd); +-} +- +-static void +-print_futex(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_pointer(arg0, 0); +- print_futex_op(arg1, 0); +- print_raw_param(",%d", arg2, 0); +- print_pointer(arg3, 0); /* struct timespec */ +- print_pointer(arg4, 0); +- print_raw_param("%d", arg4, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-#ifdef TARGET_NR_kill +-static void +-print_kill(const struct syscallname *name, +- abi_long arg0, abi_long arg1, abi_long arg2, +- abi_long arg3, abi_long arg4, abi_long arg5) +-{ +- print_syscall_prologue(name); +- print_raw_param("%d", arg0, 0); +- print_signal(arg1, 1); +- print_syscall_epilogue(name); +-} +-#endif +- +-/* +- * An array of all of the syscalls we know about +- */ +- +-static const struct syscallname scnames[] = { +-#include "strace.list" +-}; +- +-static int nsyscalls = ARRAY_SIZE(scnames); + + /* + * The public interface to this module. +@@ -1570,49 +101,77 @@ print_syscall(int num, + abi_long arg1, abi_long arg2, abi_long arg3, + abi_long arg4, abi_long arg5, abi_long arg6) + { +- int i; +- const char *format="%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ")"; +- + gemu_log("%d ", getpid() ); +- +- for(i=0;i + #include + #include +-#include "linux_loop.h" +-#include "uname.h" + + #include "qemu.h" + +-#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \ +- CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID) +- + //#define DEBUG + +-//#include +-#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct linux_dirent [2]) +-#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct linux_dirent [2]) +- + + #undef _syscall0 + #undef _syscall1 +@@ -180,408 +171,200 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \ + } + + +-#define __NR_sys_uname __NR_uname +-#define __NR_sys_getcwd1 __NR_getcwd +-#define __NR_sys_getdents __NR_getdents +-#define __NR_sys_getdents64 __NR_getdents64 +-#define __NR_sys_getpriority __NR_getpriority +-#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo +-#define __NR_sys_syslog __NR_syslog +-#define __NR_sys_tgkill __NR_tgkill +-#define __NR_sys_tkill __NR_tkill +-#define __NR_sys_futex __NR_futex +-#define __NR_sys_inotify_init __NR_inotify_init +-#define __NR_sys_inotify_add_watch __NR_inotify_add_watch +-#define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch +- +-#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__) || \ +- defined(__s390x__) +-#define __NR__llseek __NR_lseek +-#endif +- +-/* Newer kernel ports have llseek() instead of _llseek() */ +-#if defined(TARGET_NR_llseek) && !defined(TARGET_NR__llseek) +-#define TARGET_NR__llseek TARGET_NR_llseek +-#endif +- +-#ifdef __NR_gettid +-_syscall0(int, gettid) +-#else +-/* This is a replacement for the host gettid() and must return a host +- errno. */ +-static int gettid(void) { +- return -ENOSYS; +-} +-#endif +-#ifdef __NR_getdents +-_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count); +-#endif +-#if !defined(__NR_getdents) || \ +- (defined(TARGET_NR_getdents64) && defined(__NR_getdents64)) +-_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count); +-#endif +-#if defined(TARGET_NR__llseek) && defined(__NR_llseek) +-_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, +- loff_t *, res, uint, wh); +-#endif +-_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo) +-_syscall3(int,sys_syslog,int,type,char*,bufp,int,len) +-#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill) +-_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig) +-#endif +-#if defined(TARGET_NR_tkill) && defined(__NR_tkill) +-_syscall2(int,sys_tkill,int,tid,int,sig) +-#endif ++#ifndef AFL + #ifdef __NR_exit_group + _syscall1(int,exit_group,int,error_code) + #endif +-#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address) +-_syscall1(int,set_tid_address,int *,tidptr) +-#endif +-#if defined(TARGET_NR_futex) && defined(__NR_futex) +-_syscall6(int,sys_futex,int *,uaddr,int,op,int,val, +- const struct timespec *,timeout,int *,uaddr2,int,val3) +-#endif +-#define __NR_sys_sched_getaffinity __NR_sched_getaffinity +-_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len, +- unsigned long *, user_mask_ptr); +-#define __NR_sys_sched_setaffinity __NR_sched_setaffinity +-_syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len, +- unsigned long *, user_mask_ptr); +-_syscall4(int, reboot, int, magic1, int, magic2, unsigned int, cmd, +- void *, arg); +-_syscall2(int, capget, struct __user_cap_header_struct *, header, +- struct __user_cap_data_struct *, data); +-_syscall2(int, capset, struct __user_cap_header_struct *, header, +- struct __user_cap_data_struct *, data); +-#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get) +-_syscall2(int, ioprio_get, int, which, int, who) +-#endif +-#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set) +-_syscall3(int, ioprio_set, int, which, int, who, int, ioprio) + #endif + +-static bitmask_transtbl fcntl_flags_tbl[] = { +- { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, }, +- { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, }, +- { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, }, +- { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, }, +- { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, }, +- { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, }, +- { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, }, +- { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, }, +- { TARGET_O_SYNC, TARGET_O_DSYNC, O_SYNC, O_DSYNC, }, +- { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, }, +- { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, }, +- { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, }, +- { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, }, +-#if defined(O_DIRECT) +- { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, }, +-#endif +-#if defined(O_NOATIME) +- { TARGET_O_NOATIME, TARGET_O_NOATIME, O_NOATIME, O_NOATIME }, +-#endif +-#if defined(O_CLOEXEC) +- { TARGET_O_CLOEXEC, TARGET_O_CLOEXEC, O_CLOEXEC, O_CLOEXEC }, +-#endif +-#if defined(O_PATH) +- { TARGET_O_PATH, TARGET_O_PATH, O_PATH, O_PATH }, ++ ++/* CGC TODO: which select? */ ++#if defined(TARGET_NR_pselect6) ++#ifndef __NR_pselect6 ++# define __NR_pselect6 -1 + #endif +- /* Don't terminate the list prematurely on 64-bit host+guest. */ +-#if TARGET_O_LARGEFILE != 0 || O_LARGEFILE != 0 +- { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, }, ++#define __NR_sys_pselect6 __NR_pselect6 ++_syscall6(int, sys_pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds, ++ fd_set *, exceptfds, struct timespec *, timeout, void *, sig); + #endif +- { 0, 0, 0, 0 } +-}; + +-static int sys_getcwd1(char *buf, size_t size) +-{ +- if (getcwd(buf, size) == NULL) { +- /* getcwd() sets errno */ +- return (-1); +- } +- return strlen(buf)+1; +-} ++int report_bad_args = 0; ++int enabled_double_empty_exiting = 0; + +-static int sys_openat(int dirfd, const char *pathname, int flags, mode_t mode) +-{ +- /* +- * open(2) has extra parameter 'mode' when called with +- * flag O_CREAT. +- */ +- if ((flags & O_CREAT) != 0) { +- return (openat(dirfd, pathname, flags, mode)); +- } +- return (openat(dirfd, pathname, flags)); +-} ++#ifdef AFL ++int possibly_controlled_buf = 0; + +-#ifdef TARGET_NR_utimensat +-#ifdef CONFIG_UTIMENSAT +-static int sys_utimensat(int dirfd, const char *pathname, +- const struct timespec times[2], int flags) +-{ +- if (pathname == NULL) +- return futimens(dirfd, times); +- else +- return utimensat(dirfd, pathname, times, flags); +-} +-#elif defined(__NR_utimensat) +-#define __NR_sys_utimensat __NR_utimensat +-_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname, +- const struct timespec *,tsp,int,flags) +-#else +-static int sys_utimensat(int dirfd, const char *pathname, +- const struct timespec times[2], int flags) +-{ +- errno = ENOSYS; +- return -1; +-} +-#endif +-#endif /* TARGET_NR_utimensat */ + +-#ifdef CONFIG_INOTIFY +-#include ++int exit_group(int error_code) { ++ if (possibly_controlled_buf) ++ raise(SIGSEGV); + +-#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init) +-static int sys_inotify_init(void) +-{ +- return (inotify_init()); ++ syscall(__NR_exit_group, error_code); + } + #endif +-#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch) +-static int sys_inotify_add_watch(int fd,const char *pathname, int32_t mask) +-{ +- return (inotify_add_watch(fd, pathname, mask)); +-} ++ ++#ifdef AFL ++unsigned first_recv = 1; + #endif +-#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch) +-static int sys_inotify_rm_watch(int fd, int32_t wd) +-{ +- return (inotify_rm_watch(fd, wd)); +-} ++static unsigned zero_recv_hits = 0; ++#if defined(TRACER) || defined(AFL) ++static unsigned first_recv_hit = false; + #endif +-#ifdef CONFIG_INOTIFY1 +-#if defined(TARGET_NR_inotify_init1) && defined(__NR_inotify_init1) +-static int sys_inotify_init1(int flags) ++ ++FILE *receive_count_fp = NULL; ++ ++#ifdef TRACER ++char *predump_file = NULL; ++ ++static int predump_one(void *priv, target_ulong start, ++ target_ulong end, unsigned long prot) + { +- return (inotify_init1(flags)); +-} +-#endif +-#endif +-#else +-/* Userspace can usually survive runtime without inotify */ +-#undef TARGET_NR_inotify_init +-#undef TARGET_NR_inotify_init1 +-#undef TARGET_NR_inotify_add_watch +-#undef TARGET_NR_inotify_rm_watch +-#endif /* CONFIG_INOTIFY */ +- +-#if defined(TARGET_NR_ppoll) +-#ifndef __NR_ppoll +-# define __NR_ppoll -1 +-#endif +-#define __NR_sys_ppoll __NR_ppoll +-_syscall5(int, sys_ppoll, struct pollfd *, fds, nfds_t, nfds, +- struct timespec *, timeout, const sigset_t *, sigmask, +- size_t, sigsetsize) +-#endif ++ FILE *f; ++ target_ulong length; + +-#if defined(TARGET_NR_pselect6) +-#ifndef __NR_pselect6 +-# define __NR_pselect6 -1 +-#endif +-#define __NR_sys_pselect6 __NR_pselect6 +-_syscall6(int, sys_pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds, +- fd_set *, exceptfds, struct timespec *, timeout, void *, sig); +-#endif ++ f = (FILE *)priv; + +-#if defined(TARGET_NR_prlimit64) +-#ifndef __NR_prlimit64 +-# define __NR_prlimit64 -1 +-#endif +-#define __NR_sys_prlimit64 __NR_prlimit64 +-/* The glibc rlimit structure may not be that used by the underlying syscall */ +-struct host_rlimit64 { +- uint64_t rlim_cur; +- uint64_t rlim_max; +-}; +-_syscall4(int, sys_prlimit64, pid_t, pid, int, resource, +- const struct host_rlimit64 *, new_limit, +- struct host_rlimit64 *, old_limit) +-#endif ++ length = end - start; ++ ++ fwrite(&start, sizeof(target_ulong), 1, f); ++ fwrite(&end, sizeof(target_ulong), 1, f); ++ fwrite(&prot, sizeof(target_ulong), 1, f); ++ fwrite(&length, sizeof(target_ulong), 1, f); + ++ fwrite(g2h(start), length, 1, f); + +-#if defined(TARGET_NR_timer_create) +-/* Maxiumum of 32 active POSIX timers allowed at any one time. */ +-static timer_t g_posix_timers[32] = { 0, } ; ++ return 0; ++} + +-static inline int next_free_host_timer(void) ++static int do_predump(char *file, CPUX86State *env) + { +- int k ; +- /* FIXME: Does finding the next free slot require a lock? */ +- for (k = 0; k < ARRAY_SIZE(g_posix_timers); k++) { +- if (g_posix_timers[k] == 0) { +- g_posix_timers[k] = (timer_t) 1; +- return k; +- } ++ FILE *f; ++ ++ f = fopen(file, "w"); ++ if (f == NULL) { ++ perror("predump file open"); ++ return -1; + } +- return -1; +-} +-#endif + +-/* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */ +-#ifdef TARGET_ARM +-static inline int regpairs_aligned(void *cpu_env) { +- return ((((CPUARMState *)cpu_env)->eabi) == 1) ; ++ walk_memory_regions(f, predump_one); ++ ++ fwrite("HEAP", 4, 1, f); ++ fwrite(&mmap_next_start, 4, 1, f); ++ ++ fwrite("REGS", 4, 1, f); ++ /* write out registers */ ++ fwrite(&env->regs[R_EAX], 4, 1, f); ++ fwrite(&env->regs[R_EBX], 4, 1, f); ++ fwrite(&env->regs[R_ECX], 4, 1, f); ++ fwrite(&env->regs[R_EDX], 4, 1, f); ++ fwrite(&env->regs[R_ESI], 4, 1, f); ++ fwrite(&env->regs[R_EDI], 4, 1, f); ++ fwrite(&env->regs[R_EBP], 4, 1, f); ++ fwrite(&env->regs[R_ESP], 4, 1, f); ++ ++ /* write out d flag */ ++ fwrite(&env->df, 4, 1, f); ++ ++ /* write out eip */ ++ fwrite(&env->eip, 4, 1, f); ++ ++ /* write out fp registers */ ++ fwrite(&env->fpregs[0], sizeof(FPReg), 1, f); ++ fwrite(&env->fpregs[1], sizeof(FPReg), 1, f); ++ fwrite(&env->fpregs[2], sizeof(FPReg), 1, f); ++ fwrite(&env->fpregs[3], sizeof(FPReg), 1, f); ++ fwrite(&env->fpregs[4], sizeof(FPReg), 1, f); ++ fwrite(&env->fpregs[5], sizeof(FPReg), 1, f); ++ fwrite(&env->fpregs[6], sizeof(FPReg), 1, f); ++ fwrite(&env->fpregs[7], sizeof(FPReg), 1, f); ++ ++ /* write out fp tags */ ++ fwrite(&env->fptags[0], 1, 1, f); ++ fwrite(&env->fptags[1], 1, 1, f); ++ fwrite(&env->fptags[2], 1, 1, f); ++ fwrite(&env->fptags[3], 1, 1, f); ++ fwrite(&env->fptags[4], 1, 1, f); ++ fwrite(&env->fptags[5], 1, 1, f); ++ fwrite(&env->fptags[6], 1, 1, f); ++ fwrite(&env->fptags[7], 1, 1, f); ++ ++ /* ftop */ ++ fwrite(&env->fpstt, 4, 1, f); ++ ++ /* sseround */ ++ fwrite(&env->mxcsr, 4, 1, f); ++ ++ /* write out xmm registers */ ++ fwrite(&env->xmm_regs[0], 16, 1, f); ++ fwrite(&env->xmm_regs[1], 16, 1, f); ++ fwrite(&env->xmm_regs[2], 16, 1, f); ++ fwrite(&env->xmm_regs[3], 16, 1, f); ++ fwrite(&env->xmm_regs[4], 16, 1, f); ++ fwrite(&env->xmm_regs[5], 16, 1, f); ++ fwrite(&env->xmm_regs[6], 16, 1, f); ++ fwrite(&env->xmm_regs[7], 16, 1, f); ++ ++ fclose(f); ++ return 0; + } +-#elif defined(TARGET_MIPS) +-static inline int regpairs_aligned(void *cpu_env) { return 1; } +-#elif defined(TARGET_PPC) && !defined(TARGET_PPC64) +-/* SysV AVI for PPC32 expects 64bit parameters to be passed on odd/even pairs +- * of registers which translates to the same as ARM/MIPS, because we start with +- * r3 as arg1 */ +-static inline int regpairs_aligned(void *cpu_env) { return 1; } +-#else +-static inline int regpairs_aligned(void *cpu_env) { return 0; } +-#endif ++#endif /* TRACER */ + +-#define ERRNO_TABLE_SIZE 1200 + +-/* target_to_host_errno_table[] is initialized from +- * host_to_target_errno_table[] in syscall_init(). */ +-static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = { +-}; +- +-/* +- * This list is the union of errno values overridden in asm-/errno.h +- * minus the errnos that are not actually generic to all archs. +- */ +-static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = { +- [EIDRM] = TARGET_EIDRM, +- [ECHRNG] = TARGET_ECHRNG, +- [EL2NSYNC] = TARGET_EL2NSYNC, +- [EL3HLT] = TARGET_EL3HLT, +- [EL3RST] = TARGET_EL3RST, +- [ELNRNG] = TARGET_ELNRNG, +- [EUNATCH] = TARGET_EUNATCH, +- [ENOCSI] = TARGET_ENOCSI, +- [EL2HLT] = TARGET_EL2HLT, +- [EDEADLK] = TARGET_EDEADLK, +- [ENOLCK] = TARGET_ENOLCK, +- [EBADE] = TARGET_EBADE, +- [EBADR] = TARGET_EBADR, +- [EXFULL] = TARGET_EXFULL, +- [ENOANO] = TARGET_ENOANO, +- [EBADRQC] = TARGET_EBADRQC, +- [EBADSLT] = TARGET_EBADSLT, +- [EBFONT] = TARGET_EBFONT, +- [ENOSTR] = TARGET_ENOSTR, +- [ENODATA] = TARGET_ENODATA, +- [ETIME] = TARGET_ETIME, +- [ENOSR] = TARGET_ENOSR, +- [ENONET] = TARGET_ENONET, +- [ENOPKG] = TARGET_ENOPKG, +- [EREMOTE] = TARGET_EREMOTE, +- [ENOLINK] = TARGET_ENOLINK, +- [EADV] = TARGET_EADV, +- [ESRMNT] = TARGET_ESRMNT, +- [ECOMM] = TARGET_ECOMM, +- [EPROTO] = TARGET_EPROTO, +- [EDOTDOT] = TARGET_EDOTDOT, +- [EMULTIHOP] = TARGET_EMULTIHOP, +- [EBADMSG] = TARGET_EBADMSG, +- [ENAMETOOLONG] = TARGET_ENAMETOOLONG, +- [EOVERFLOW] = TARGET_EOVERFLOW, +- [ENOTUNIQ] = TARGET_ENOTUNIQ, +- [EBADFD] = TARGET_EBADFD, +- [EREMCHG] = TARGET_EREMCHG, +- [ELIBACC] = TARGET_ELIBACC, +- [ELIBBAD] = TARGET_ELIBBAD, +- [ELIBSCN] = TARGET_ELIBSCN, +- [ELIBMAX] = TARGET_ELIBMAX, +- [ELIBEXEC] = TARGET_ELIBEXEC, +- [EILSEQ] = TARGET_EILSEQ, +- [ENOSYS] = TARGET_ENOSYS, +- [ELOOP] = TARGET_ELOOP, +- [ERESTART] = TARGET_ERESTART, +- [ESTRPIPE] = TARGET_ESTRPIPE, +- [ENOTEMPTY] = TARGET_ENOTEMPTY, +- [EUSERS] = TARGET_EUSERS, +- [ENOTSOCK] = TARGET_ENOTSOCK, +- [EDESTADDRREQ] = TARGET_EDESTADDRREQ, +- [EMSGSIZE] = TARGET_EMSGSIZE, +- [EPROTOTYPE] = TARGET_EPROTOTYPE, +- [ENOPROTOOPT] = TARGET_ENOPROTOOPT, +- [EPROTONOSUPPORT] = TARGET_EPROTONOSUPPORT, +- [ESOCKTNOSUPPORT] = TARGET_ESOCKTNOSUPPORT, +- [EOPNOTSUPP] = TARGET_EOPNOTSUPP, +- [EPFNOSUPPORT] = TARGET_EPFNOSUPPORT, +- [EAFNOSUPPORT] = TARGET_EAFNOSUPPORT, +- [EADDRINUSE] = TARGET_EADDRINUSE, +- [EADDRNOTAVAIL] = TARGET_EADDRNOTAVAIL, +- [ENETDOWN] = TARGET_ENETDOWN, +- [ENETUNREACH] = TARGET_ENETUNREACH, +- [ENETRESET] = TARGET_ENETRESET, +- [ECONNABORTED] = TARGET_ECONNABORTED, +- [ECONNRESET] = TARGET_ECONNRESET, +- [ENOBUFS] = TARGET_ENOBUFS, +- [EISCONN] = TARGET_EISCONN, +- [ENOTCONN] = TARGET_ENOTCONN, +- [EUCLEAN] = TARGET_EUCLEAN, +- [ENOTNAM] = TARGET_ENOTNAM, +- [ENAVAIL] = TARGET_ENAVAIL, +- [EISNAM] = TARGET_EISNAM, +- [EREMOTEIO] = TARGET_EREMOTEIO, +- [ESHUTDOWN] = TARGET_ESHUTDOWN, +- [ETOOMANYREFS] = TARGET_ETOOMANYREFS, +- [ETIMEDOUT] = TARGET_ETIMEDOUT, +- [ECONNREFUSED] = TARGET_ECONNREFUSED, +- [EHOSTDOWN] = TARGET_EHOSTDOWN, +- [EHOSTUNREACH] = TARGET_EHOSTUNREACH, +- [EALREADY] = TARGET_EALREADY, +- [EINPROGRESS] = TARGET_EINPROGRESS, +- [ESTALE] = TARGET_ESTALE, +- [ECANCELED] = TARGET_ECANCELED, +- [ENOMEDIUM] = TARGET_ENOMEDIUM, +- [EMEDIUMTYPE] = TARGET_EMEDIUMTYPE, +-#ifdef ENOKEY +- [ENOKEY] = TARGET_ENOKEY, +-#endif +-#ifdef EKEYEXPIRED +- [EKEYEXPIRED] = TARGET_EKEYEXPIRED, +-#endif +-#ifdef EKEYREVOKED +- [EKEYREVOKED] = TARGET_EKEYREVOKED, +-#endif +-#ifdef EKEYREJECTED +- [EKEYREJECTED] = TARGET_EKEYREJECTED, +-#endif +-#ifdef EOWNERDEAD +- [EOWNERDEAD] = TARGET_EOWNERDEAD, +-#endif +-#ifdef ENOTRECOVERABLE +- [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE, +-#endif +-}; + + static inline int host_to_target_errno(int err) + { +- if(host_to_target_errno_table[err]) +- return host_to_target_errno_table[err]; +- return err; ++ /* From binfmt_cgc.c cgc_map_err */ ++ switch (err) { ++ case EBADF: ++ return TARGET_EBADF; ++ case EFAULT: ++ return TARGET_EFAULT; ++ case EINVAL: ++ return TARGET_EINVAL; ++ case ENOMEM: ++ return TARGET_ENOMEM; ++ case ENOSYS: ++ return TARGET_ENOSYS; ++ case EPIPE: ++ return TARGET_EPIPE; ++ case EINTR: ++ /* CGC TODO: binfmt_cgc also includes these - they can't reach userspace, right? ++ case ERESTARTSYS: ++ case ERESTARTNOINTR: ++ case ERESTARTNOHAND: ++ case ERESTART_RESTARTBLOCK: ++ */ ++ /* CGC auto-restarts syscalls, these must never occurr */ ++ fprintf(stderr, "qemu: INTERNAL ERROR: A syscall returned EINTR: this cannot happen in CGC, we would need to automatically restart it."); ++ exit(-36); ++ } ++ return TARGET_EINVAL; + } + + static inline int target_to_host_errno(int err) + { +- if (target_to_host_errno_table[err]) +- return target_to_host_errno_table[err]; +- return err; ++ switch (err) { ++ case TARGET_EBADF: ++ return EBADF; ++ case TARGET_EFAULT: ++ return EFAULT; ++ case TARGET_EINVAL: ++ return EINVAL; ++ case TARGET_ENOMEM: ++ return ENOMEM; ++ case TARGET_ENOSYS: ++ return ENOSYS; ++ case TARGET_EPIPE: ++ return EPIPE; ++ } ++ assert(false); ++ return EBADSLT; /* Meaningless value */ + } + + static inline abi_long get_errno(abi_long ret) + { + if (ret == -1) +- return -host_to_target_errno(errno); ++ return host_to_target_errno(errno); /* Note: CGC error returns are >0 */ + else + return ret; + } +@@ -593,133 +376,12 @@ static inline int is_error(abi_long ret) + + char *target_strerror(int err) + { +- if ((err >= ERRNO_TABLE_SIZE) || (err < 0)) { +- return NULL; ++ if ((err >= 4000) || (err < 0)) { ++ return NULL; /* Can this actually happen? */ + } + return strerror(target_to_host_errno(err)); + } + +-static inline int host_to_target_sock_type(int host_type) +-{ +- int target_type; +- +- switch (host_type & 0xf /* SOCK_TYPE_MASK */) { +- case SOCK_DGRAM: +- target_type = TARGET_SOCK_DGRAM; +- break; +- case SOCK_STREAM: +- target_type = TARGET_SOCK_STREAM; +- break; +- default: +- target_type = host_type & 0xf /* SOCK_TYPE_MASK */; +- break; +- } +- +-#if defined(SOCK_CLOEXEC) +- if (host_type & SOCK_CLOEXEC) { +- target_type |= TARGET_SOCK_CLOEXEC; +- } +-#endif +- +-#if defined(SOCK_NONBLOCK) +- if (host_type & SOCK_NONBLOCK) { +- target_type |= TARGET_SOCK_NONBLOCK; +- } +-#endif +- +- return target_type; +-} +- +-static abi_ulong target_brk; +-static abi_ulong target_original_brk; +-static abi_ulong brk_page; +- +-void target_set_brk(abi_ulong new_brk) +-{ +- target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk); +- brk_page = HOST_PAGE_ALIGN(target_brk); +-} +- +-//#define DEBUGF_BRK(message, args...) do { fprintf(stderr, (message), ## args); } while (0) +-#define DEBUGF_BRK(message, args...) +- +-/* do_brk() must return target values and target errnos. */ +-abi_long do_brk(abi_ulong new_brk) +-{ +- abi_long mapped_addr; +- int new_alloc_size; +- +- DEBUGF_BRK("do_brk(" TARGET_ABI_FMT_lx ") -> ", new_brk); +- +- if (!new_brk) { +- DEBUGF_BRK(TARGET_ABI_FMT_lx " (!new_brk)\n", target_brk); +- return target_brk; +- } +- if (new_brk < target_original_brk) { +- DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk < target_original_brk)\n", +- target_brk); +- return target_brk; +- } +- +- /* If the new brk is less than the highest page reserved to the +- * target heap allocation, set it and we're almost done... */ +- if (new_brk <= brk_page) { +- /* Heap contents are initialized to zero, as for anonymous +- * mapped pages. */ +- if (new_brk > target_brk) { +- memset(g2h(target_brk), 0, new_brk - target_brk); +- } +- target_brk = new_brk; +- DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk <= brk_page)\n", target_brk); +- return target_brk; +- } +- +- /* We need to allocate more memory after the brk... Note that +- * we don't use MAP_FIXED because that will map over the top of +- * any existing mapping (like the one with the host libc or qemu +- * itself); instead we treat "mapped but at wrong address" as +- * a failure and unmap again. +- */ +- new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page); +- mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size, +- PROT_READ|PROT_WRITE, +- MAP_ANON|MAP_PRIVATE, 0, 0)); +- +- if (mapped_addr == brk_page) { +- /* Heap contents are initialized to zero, as for anonymous +- * mapped pages. Technically the new pages are already +- * initialized to zero since they *are* anonymous mapped +- * pages, however we have to take care with the contents that +- * come from the remaining part of the previous page: it may +- * contains garbage data due to a previous heap usage (grown +- * then shrunken). */ +- memset(g2h(target_brk), 0, brk_page - target_brk); +- +- target_brk = new_brk; +- brk_page = HOST_PAGE_ALIGN(target_brk); +- DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr == brk_page)\n", +- target_brk); +- return target_brk; +- } else if (mapped_addr != -1) { +- /* Mapped but at wrong address, meaning there wasn't actually +- * enough space for this brk. +- */ +- target_munmap(mapped_addr, new_alloc_size); +- mapped_addr = -1; +- DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr != -1)\n", target_brk); +- } +- else { +- DEBUGF_BRK(TARGET_ABI_FMT_lx " (otherwise)\n", target_brk); +- } +- +-#if defined(TARGET_ALPHA) +- /* We (partially) emulate OSF/1 on Alpha, which requires we +- return a proper errno, not an unchanged brk value. */ +- return -TARGET_ENOMEM; +-#endif +- /* For everything else, return the previous break. */ +- return target_brk; +-} + + static inline abi_long copy_from_user_fdset(fd_set *fds, + abi_ulong target_fds_addr, +@@ -733,7 +395,7 @@ static inline abi_long copy_from_user_fdset(fd_set *fds, + target_fds_addr, + sizeof(abi_ulong) * nw, + 1))) +- return -TARGET_EFAULT; ++ return TARGET_EFAULT; + + FD_ZERO(fds); + k = 0; +@@ -759,7 +421,7 @@ static inline abi_ulong copy_from_user_fdset_ptr(fd_set *fds, fd_set **fds_ptr, + { + if (target_fds_addr) { + if (copy_from_user_fdset(fds, target_fds_addr, n)) +- return -TARGET_EFAULT; ++ return TARGET_EFAULT; + *fds_ptr = fds; + } else { + *fds_ptr = NULL; +@@ -780,7 +442,7 @@ static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr, + target_fds_addr, + sizeof(abi_ulong) * nw, + 0))) +- return -TARGET_EFAULT; ++ return TARGET_EFAULT; + + k = 0; + for (i = 0; i < nw; i++) { +@@ -797,126 +459,13 @@ static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr, + return 0; + } + +-#if defined(__alpha__) +-#define HOST_HZ 1024 +-#else +-#define HOST_HZ 100 +-#endif +- +-static inline abi_long host_to_target_clock_t(long ticks) +-{ +-#if HOST_HZ == TARGET_HZ +- return ticks; +-#else +- return ((int64_t)ticks * TARGET_HZ) / HOST_HZ; +-#endif +-} +- +-static inline abi_long host_to_target_rusage(abi_ulong target_addr, +- const struct rusage *rusage) +-{ +- struct target_rusage *target_rusage; +- +- if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0)) +- return -TARGET_EFAULT; +- target_rusage->ru_utime.tv_sec = tswapal(rusage->ru_utime.tv_sec); +- target_rusage->ru_utime.tv_usec = tswapal(rusage->ru_utime.tv_usec); +- target_rusage->ru_stime.tv_sec = tswapal(rusage->ru_stime.tv_sec); +- target_rusage->ru_stime.tv_usec = tswapal(rusage->ru_stime.tv_usec); +- target_rusage->ru_maxrss = tswapal(rusage->ru_maxrss); +- target_rusage->ru_ixrss = tswapal(rusage->ru_ixrss); +- target_rusage->ru_idrss = tswapal(rusage->ru_idrss); +- target_rusage->ru_isrss = tswapal(rusage->ru_isrss); +- target_rusage->ru_minflt = tswapal(rusage->ru_minflt); +- target_rusage->ru_majflt = tswapal(rusage->ru_majflt); +- target_rusage->ru_nswap = tswapal(rusage->ru_nswap); +- target_rusage->ru_inblock = tswapal(rusage->ru_inblock); +- target_rusage->ru_oublock = tswapal(rusage->ru_oublock); +- target_rusage->ru_msgsnd = tswapal(rusage->ru_msgsnd); +- target_rusage->ru_msgrcv = tswapal(rusage->ru_msgrcv); +- target_rusage->ru_nsignals = tswapal(rusage->ru_nsignals); +- target_rusage->ru_nvcsw = tswapal(rusage->ru_nvcsw); +- target_rusage->ru_nivcsw = tswapal(rusage->ru_nivcsw); +- unlock_user_struct(target_rusage, target_addr, 1); +- +- return 0; +-} +- +-static inline rlim_t target_to_host_rlim(abi_ulong target_rlim) +-{ +- abi_ulong target_rlim_swap; +- rlim_t result; +- +- target_rlim_swap = tswapal(target_rlim); +- if (target_rlim_swap == TARGET_RLIM_INFINITY) +- return RLIM_INFINITY; +- +- result = target_rlim_swap; +- if (target_rlim_swap != (rlim_t)result) +- return RLIM_INFINITY; +- +- return result; +-} +- +-static inline abi_ulong host_to_target_rlim(rlim_t rlim) +-{ +- abi_ulong target_rlim_swap; +- abi_ulong result; +- +- if (rlim == RLIM_INFINITY || rlim != (abi_long)rlim) +- target_rlim_swap = TARGET_RLIM_INFINITY; +- else +- target_rlim_swap = rlim; +- result = tswapal(target_rlim_swap); +- +- return result; +-} +- +-static inline int target_to_host_resource(int code) +-{ +- switch (code) { +- case TARGET_RLIMIT_AS: +- return RLIMIT_AS; +- case TARGET_RLIMIT_CORE: +- return RLIMIT_CORE; +- case TARGET_RLIMIT_CPU: +- return RLIMIT_CPU; +- case TARGET_RLIMIT_DATA: +- return RLIMIT_DATA; +- case TARGET_RLIMIT_FSIZE: +- return RLIMIT_FSIZE; +- case TARGET_RLIMIT_LOCKS: +- return RLIMIT_LOCKS; +- case TARGET_RLIMIT_MEMLOCK: +- return RLIMIT_MEMLOCK; +- case TARGET_RLIMIT_MSGQUEUE: +- return RLIMIT_MSGQUEUE; +- case TARGET_RLIMIT_NICE: +- return RLIMIT_NICE; +- case TARGET_RLIMIT_NOFILE: +- return RLIMIT_NOFILE; +- case TARGET_RLIMIT_NPROC: +- return RLIMIT_NPROC; +- case TARGET_RLIMIT_RSS: +- return RLIMIT_RSS; +- case TARGET_RLIMIT_RTPRIO: +- return RLIMIT_RTPRIO; +- case TARGET_RLIMIT_SIGPENDING: +- return RLIMIT_SIGPENDING; +- case TARGET_RLIMIT_STACK: +- return RLIMIT_STACK; +- default: +- return code; +- } +-} +- + static inline abi_long copy_from_user_timeval(struct timeval *tv, +- abi_ulong target_tv_addr) ++ abi_ulong target_tv_addr) + { + struct target_timeval *target_tv; + + if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) +- return -TARGET_EFAULT; ++ return TARGET_EFAULT; + + __get_user(tv->tv_sec, &target_tv->tv_sec); + __get_user(tv->tv_usec, &target_tv->tv_usec); +@@ -927,12 +476,12 @@ static inline abi_long copy_from_user_timeval(struct timeval *tv, + } + + static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr, +- const struct timeval *tv) ++ const struct timeval *tv) + { + struct target_timeval *target_tv; + + if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) +- return -TARGET_EFAULT; ++ return TARGET_EFAULT; + + __put_user(tv->tv_sec, &target_tv->tv_sec); + __put_user(tv->tv_usec, &target_tv->tv_usec); +@@ -942,8891 +491,548 @@ static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr, + return 0; + } + +-static inline abi_long copy_from_user_timezone(struct timezone *tz, +- abi_ulong target_tz_addr) +-{ +- struct target_timezone *target_tz; +- +- if (!lock_user_struct(VERIFY_READ, target_tz, target_tz_addr, 1)) { +- return -TARGET_EFAULT; +- } ++struct sinkhole_entry { ++ abi_ulong addr; ++ size_t length; ++ struct sinkhole_entry *next; ++ struct sinkhole_entry *prev; ++}; + +- __get_user(tz->tz_minuteswest, &target_tz->tz_minuteswest); +- __get_user(tz->tz_dsttime, &target_tz->tz_dsttime); ++struct sinkhole_entry *sinkhole_head = NULL; + +- unlock_user_struct(target_tz, target_tz_addr, 0); ++void add_sinkhole(abi_ulong, size_t); ++abi_ulong get_max_sinkhole(size_t); ++void print_sinkholes(void); + +- return 0; +-} ++void add_sinkhole(abi_ulong a, size_t length) { ++ struct sinkhole_entry *nse; + +-#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open) +-#include ++ nse = malloc(sizeof(struct sinkhole_entry)); ++ nse->addr = a; ++ nse->length = length; ++ nse->next = NULL; ++ nse->prev = NULL; + +-static inline abi_long copy_from_user_mq_attr(struct mq_attr *attr, +- abi_ulong target_mq_attr_addr) +-{ +- struct target_mq_attr *target_mq_attr; ++ /* head insertion */ ++ if (sinkhole_head) { + +- if (!lock_user_struct(VERIFY_READ, target_mq_attr, +- target_mq_attr_addr, 1)) +- return -TARGET_EFAULT; ++ nse->next = sinkhole_head; ++ nse->prev = NULL; + +- __get_user(attr->mq_flags, &target_mq_attr->mq_flags); +- __get_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg); +- __get_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize); +- __get_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs); ++ if (sinkhole_head->prev) { ++ printf("ERROR: sinkhole_head->prev should always be NULL\n"); ++ } + +- unlock_user_struct(target_mq_attr, target_mq_attr_addr, 0); ++ sinkhole_head->prev = nse; + +- return 0; ++ sinkhole_head = nse; ++ } else { ++ sinkhole_head = nse; ++ } + } + +-static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr, +- const struct mq_attr *attr) +-{ +- struct target_mq_attr *target_mq_attr; ++abi_ulong get_max_sinkhole(size_t length) { ++ struct sinkhole_entry *current, *max; ++ abi_ulong max_addr = 0; ++ ++ current = sinkhole_head; ++ while(current) { ++ if (current->length >= length && current->addr > max_addr) { ++ max_addr = current->addr; ++ max = current; ++ } ++ current = current->next; ++ } + +- if (!lock_user_struct(VERIFY_WRITE, target_mq_attr, +- target_mq_attr_addr, 0)) +- return -TARGET_EFAULT; ++ if (!max_addr) ++ return 0; + +- __put_user(attr->mq_flags, &target_mq_attr->mq_flags); +- __put_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg); +- __put_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize); +- __put_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs); ++ size_t remaining = max->length - length; ++ max_addr = max->addr + remaining; ++ max->length = remaining; + +- unlock_user_struct(target_mq_attr, target_mq_attr_addr, 1); ++ /* remove node if it's empty */ ++ if (!max->length) { ++ if (max->prev) { ++ max->prev->next = max->next; ++ } ++ if (max->next) { ++ max->next->prev = max->prev; ++ } ++ if (sinkhole_head == max) { ++ sinkhole_head = max->next; ++ } ++ free(max); ++ } + +- return 0; ++ return max_addr; ++} ++ ++void print_sinkholes(void) { ++ struct sinkhole_entry *current; ++ current = sinkhole_head; ++ while (current) { ++ printf("addr: %x, length: %x\n", current->addr, (unsigned int)current->length); ++ current = current->next; ++ } + } +-#endif + +-#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) +-/* do_select() must return target values and target errnos. */ +-static abi_long do_select(int n, +- abi_ulong rfd_addr, abi_ulong wfd_addr, +- abi_ulong efd_addr, abi_ulong target_tv_addr) ++void syscall_init(void) + { +- fd_set rfds, wfds, efds; +- fd_set *rfds_ptr, *wfds_ptr, *efds_ptr; +- struct timeval tv, *tv_ptr; +- abi_long ret; ++} + +- ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n); +- if (ret) { +- return ret; +- } +- ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n); +- if (ret) { +- return ret; ++ ++/* Map host to target signal numbers for the wait family of syscalls. ++ Assume all other status bits are the same. */ ++int host_to_target_waitstatus(int status) ++{ ++ if (WIFSIGNALED(status)) { ++ return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f); + } +- ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n); +- if (ret) { +- return ret; ++ if (WIFSTOPPED(status)) { ++ return (host_to_target_signal(WSTOPSIG(status)) << 8) ++ | (status & 0xff); + } ++ return status; ++} + +- if (target_tv_addr) { +- if (copy_from_user_timeval(&tv, target_tv_addr)) +- return -TARGET_EFAULT; +- tv_ptr = &tv; +- } else { +- tv_ptr = NULL; +- } + +- ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr)); + +- if (!is_error(ret)) { +- if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n)) +- return -TARGET_EFAULT; +- if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n)) +- return -TARGET_EFAULT; +- if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n)) +- return -TARGET_EFAULT; ++_Static_assert(sizeof(abi_long) == 4, "abi_long is not 4 bytes!"); ++_Static_assert(sizeof(abi_int) == 4, "abi_int is not 4 bytes!"); + +- if (target_tv_addr && copy_to_user_timeval(target_tv_addr, &tv)) +- return -TARGET_EFAULT; +- } ++extern int bitflip; + +- return ret; +-} +-#endif + +-static abi_long do_pipe2(int host_pipe[], int flags) +-{ +-#ifdef CONFIG_PIPE2 +- return pipe2(host_pipe, flags); ++/* The functions are approximate copies of the kernel code */ ++/* Note: usually even qemu's original code does not call unlock_user on errors. ++ * (And unless DEBUG_REMAP is defined it's a no-op anyway.) */ ++ ++#if defined(TRACER) || defined(AFL) ++static abi_long do_receive(CPUX86State *env, abi_long fd, abi_ulong buf, abi_long count, abi_ulong p_rx_bytes) { + #else +- return -ENOSYS; ++static abi_long do_receive(abi_long fd, abi_ulong buf, abi_long count, abi_ulong p_rx_bytes) { ++#endif ++#ifdef AFL ++ /* start the forkserver on the first call to receive to save even more time */ ++ if (first_recv) ++ { ++ afl_setup(); ++ afl_forkserver(env); ++ first_recv = 0; ++ } + #endif +-} + +-static abi_long do_pipe(void *cpu_env, abi_ulong pipedes, +- int flags, int is_pipe2) +-{ +- int host_pipe[2]; +- abi_long ret; +- ret = flags ? do_pipe2(host_pipe, flags) : pipe(host_pipe); ++ int ret = 0; ++ abi_ulong *p; abi_long *prx; + +- if (is_error(ret)) +- return get_errno(ret); ++ /* adjust receive to use stdin if it requests stdout */ ++ if (fd == 1) fd = 0; + +- /* Several targets have special calling conventions for the original +- pipe syscall, but didn't replicate this into the pipe2 syscall. */ +- if (!is_pipe2) { +-#if defined(TARGET_ALPHA) +- ((CPUAlphaState *)cpu_env)->ir[IR_A4] = host_pipe[1]; +- return host_pipe[0]; +-#elif defined(TARGET_MIPS) +- ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = host_pipe[1]; +- return host_pipe[0]; +-#elif defined(TARGET_SH4) +- ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1]; +- return host_pipe[0]; +-#elif defined(TARGET_SPARC) +- ((CPUSPARCState*)cpu_env)->regwptr[1] = host_pipe[1]; +- return host_pipe[0]; ++#if defined(TRACER) || defined(AFL) ++ /* predump the state for cle */ ++ if (!first_recv_hit) ++ { ++#ifdef TRACER ++ if (predump_file) ++ { ++ do_predump(predump_file, env); ++ exit_group(0); ++ } + #endif ++ first_recv_hit = true; + } ++#endif + +- if (put_user_s32(host_pipe[0], pipedes) +- || put_user_s32(host_pipe[1], pipedes + sizeof(host_pipe[0]))) +- return -TARGET_EFAULT; +- return get_errno(ret); +-} ++ if (p_rx_bytes != 0) { ++ if (!(prx = lock_user(VERIFY_WRITE, p_rx_bytes, 4, 0))) { + +-static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn, +- abi_ulong target_addr, +- socklen_t len) +-{ +- struct target_ip_mreqn *target_smreqn; ++ return TARGET_EFAULT; ++ } ++ } else prx = NULL; + +- target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1); +- if (!target_smreqn) +- return -TARGET_EFAULT; +- mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr; +- mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr; +- if (len == sizeof(struct target_ip_mreqn)) +- mreqn->imr_ifindex = tswapal(target_smreqn->imr_ifindex); +- unlock_user(target_smreqn, target_addr, 0); ++ /* Shortens the count to valid pages only. ++ * TODO: check, see translate_all.c */ ++ __attribute__((unused)) const abi_long req_count = count; ++ count = valid_len(buf, count, PAGE_READ|PAGE_WRITE); ++#ifdef DEBUG_LENIENT_LENGTHS ++ if (count < req_count) ++ fprintf(stderr, "FOR_CGC: Pre-shortening receive count=%d to %d\n", req_count, count); ++#endif + +- return 0; +-} ++ if (!(p = lock_user(VERIFY_WRITE, buf, count, 0))) { ++#ifdef AFL ++ possibly_controlled_buf = 1; ++#endif ++ if (report_bad_args) ++ raise(SIGSEGV); + +-static inline abi_long target_to_host_sockaddr(struct sockaddr *addr, +- abi_ulong target_addr, +- socklen_t len) +-{ +- const socklen_t unix_maxlen = sizeof (struct sockaddr_un); +- sa_family_t sa_family; +- struct target_sockaddr *target_saddr; +- +- target_saddr = lock_user(VERIFY_READ, target_addr, len, 1); +- if (!target_saddr) +- return -TARGET_EFAULT; +- +- sa_family = tswap16(target_saddr->sa_family); +- +- /* Oops. The caller might send a incomplete sun_path; sun_path +- * must be terminated by \0 (see the manual page), but +- * unfortunately it is quite common to specify sockaddr_un +- * length as "strlen(x->sun_path)" while it should be +- * "strlen(...) + 1". We'll fix that here if needed. +- * Linux kernel has a similar feature. +- */ +- +- if (sa_family == AF_UNIX) { +- if (len < unix_maxlen && len > 0) { +- char *cp = (char*)target_saddr; +- +- if ( cp[len-1] && !cp[len] ) +- len++; +- } +- if (len > unix_maxlen) +- len = unix_maxlen; ++ return TARGET_EFAULT; ++ } ++ if (count < 0) /* The kernel does this in rw_verify_area, if I understand correctly */ ++ return TARGET_EINVAL; ++ ++ if (count != 0) { ++ do { ++ ret = read(fd, p, count); ++ } while ((ret == -1) && (errno == EINTR)); ++ if (ret >= 0) { ++ if (bitflip) { ++ int i; ++ for (i = 0; i < ret; i++){ ++ unsigned char* pc = (unsigned char*)p; ++ if(pc[i]==0x00){ ++ pc[i] = 0x43; ++ }else if(pc[i]==0x43){ ++ pc[i] = 0x0a; ++ }else if(pc[i]==0xa){ ++ pc[i] = 0x31; ++ }else if(pc[i]==0x31){ ++ pc[i] = 0x00; ++ } ++ } ++ } ++ if (receive_count_fp) { ++ fprintf(receive_count_fp, "%u %u\n", ret, count); ++ } ++ unlock_user(p, buf, ret); ++ } else return get_errno(ret); + } + +- memcpy(addr, target_saddr, len); +- addr->sa_family = sa_family; +- if (sa_family == AF_PACKET) { +- struct target_sockaddr_ll *lladdr; + +- lladdr = (struct target_sockaddr_ll *)addr; +- lladdr->sll_ifindex = tswap32(lladdr->sll_ifindex); +- lladdr->sll_hatype = tswap16(lladdr->sll_hatype); ++ if (enabled_double_empty_exiting) { ++ /* if we recv 0 two times in a row exit */ ++ if (ret == 0) ++ { ++ if (zero_recv_hits > 0) ++ exit_group(1); ++ else ++ zero_recv_hits++; ++ } ++ else ++ { ++ zero_recv_hits = 0; ++ } + } +- unlock_user(target_saddr, target_addr, 0); + ++ if (prx != NULL) { ++ __put_user(ret, prx); ++ unlock_user(prx, p_rx_bytes, 4); ++ } + return 0; + } + +-static inline abi_long host_to_target_sockaddr(abi_ulong target_addr, +- struct sockaddr *addr, +- socklen_t len) +-{ +- struct target_sockaddr *target_saddr; ++static abi_long do_transmit(abi_long fd, abi_ulong buf, abi_long count, abi_ulong p_tx_bytes) { ++ int ret = 0; ++ abi_ulong *p; abi_long *ptx; + +- target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0); +- if (!target_saddr) +- return -TARGET_EFAULT; +- memcpy(target_saddr, addr, len); +- target_saddr->sa_family = tswap16(addr->sa_family); +- unlock_user(target_saddr, target_addr, len); ++ /* adjust transmit to use stdout if it requests stdin */ ++ if (fd == 0) fd = 1; + +- return 0; +-} ++ if (p_tx_bytes != 0) { ++ if (!(ptx = lock_user(VERIFY_WRITE, p_tx_bytes, 4, 0))) ++ return TARGET_EFAULT; ++ } else ptx = NULL; + +-static inline abi_long target_to_host_cmsg(struct msghdr *msgh, +- struct target_msghdr *target_msgh) +-{ +- struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh); +- abi_long msg_controllen; +- abi_ulong target_cmsg_addr; +- struct target_cmsghdr *target_cmsg; +- socklen_t space = 0; +- +- msg_controllen = tswapal(target_msgh->msg_controllen); +- if (msg_controllen < sizeof (struct target_cmsghdr)) +- goto the_end; +- target_cmsg_addr = tswapal(target_msgh->msg_control); +- target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1); +- if (!target_cmsg) +- return -TARGET_EFAULT; +- +- while (cmsg && target_cmsg) { +- void *data = CMSG_DATA(cmsg); +- void *target_data = TARGET_CMSG_DATA(target_cmsg); +- +- int len = tswapal(target_cmsg->cmsg_len) +- - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr)); +- +- space += CMSG_SPACE(len); +- if (space > msgh->msg_controllen) { +- space -= CMSG_SPACE(len); +- gemu_log("Host cmsg overflow\n"); +- break; +- } ++ /* Shortens the count to valid pages only. ++ * TODO: check, see translate_all.c */ ++ __attribute__((unused)) const abi_long req_count = count; ++ count = valid_len(buf, count, PAGE_READ); ++#ifdef DEBUG_LENIENT_LENGTHS ++ if (count < req_count) ++ fprintf(stderr, "FOR_CGC: Pre-shortening transmit count=%d to %d\n", req_count, count); ++#endif + +- if (tswap32(target_cmsg->cmsg_level) == TARGET_SOL_SOCKET) { +- cmsg->cmsg_level = SOL_SOCKET; +- } else { +- cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level); +- } +- cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type); +- cmsg->cmsg_len = CMSG_LEN(len); +- +- if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { +- int *fd = (int *)data; +- int *target_fd = (int *)target_data; +- int i, numfds = len / sizeof(int); +- +- for (i = 0; i < numfds; i++) +- fd[i] = tswap32(target_fd[i]); +- } else if (cmsg->cmsg_level == SOL_SOCKET +- && cmsg->cmsg_type == SCM_CREDENTIALS) { +- struct ucred *cred = (struct ucred *)data; +- struct target_ucred *target_cred = +- (struct target_ucred *)target_data; +- +- __put_user(target_cred->pid, &cred->pid); +- __put_user(target_cred->uid, &cred->uid); +- __put_user(target_cred->gid, &cred->gid); +- } else { +- gemu_log("Unsupported ancillary data: %d/%d\n", +- cmsg->cmsg_level, cmsg->cmsg_type); +- memcpy(data, target_data, len); +- } ++ if (!(p = lock_user(VERIFY_READ, buf, count, 1))) { ++#ifdef AFL ++ possibly_controlled_buf = 1; ++#endif ++ if (report_bad_args) ++ raise(SIGSEGV); ++ ++ return TARGET_EFAULT; ++ } ++ if (count < 0) /* The kernel does this in rw_verify_area, if I understand correctly */ ++ return TARGET_EINVAL; ++ ++ if (count != 0) { ++ do { ++ ret = write(fd, p, count); ++ } while ((ret == -1) && (errno == EINTR)); ++ if (ret >= 0) ++ unlock_user(p, buf, 0); ++ else return get_errno(ret); ++ } + +- cmsg = CMSG_NXTHDR(msgh, cmsg); +- target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg); ++ if (ptx != NULL) { ++ __put_user(ret, ptx); ++ unlock_user(ptx, p_tx_bytes, 4); + } +- unlock_user(target_cmsg, target_cmsg_addr, 0); +- the_end: +- msgh->msg_controllen = space; + return 0; + } + +-static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh, +- struct msghdr *msgh) ++static abi_long do_random(abi_ulong buf, abi_long count, abi_ulong p_rnd_out) + { +- struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh); +- abi_long msg_controllen; +- abi_ulong target_cmsg_addr; +- struct target_cmsghdr *target_cmsg; +- socklen_t space = 0; +- +- msg_controllen = tswapal(target_msgh->msg_controllen); +- if (msg_controllen < sizeof (struct target_cmsghdr)) +- goto the_end; +- target_cmsg_addr = tswapal(target_msgh->msg_control); +- target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0); +- if (!target_cmsg) +- return -TARGET_EFAULT; +- +- while (cmsg && target_cmsg) { +- void *data = CMSG_DATA(cmsg); +- void *target_data = TARGET_CMSG_DATA(target_cmsg); +- +- int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr)); +- +- space += TARGET_CMSG_SPACE(len); +- if (space > msg_controllen) { +- space -= TARGET_CMSG_SPACE(len); +- gemu_log("Target cmsg overflow\n"); +- break; +- } ++ /* DIFFERS FROM binfmt_cgc: 16-bits at a time here (rand returns 31 bits, not 32). */ + +- if (cmsg->cmsg_level == SOL_SOCKET) { +- target_cmsg->cmsg_level = tswap32(TARGET_SOL_SOCKET); ++ size_t size, i; ++ uint16_t randval; ++ int ret; ++ abi_ulong *pout; ++ if (p_rnd_out != 0) { ++ if (!(pout = lock_user(VERIFY_WRITE, p_rnd_out, 4, 0))) ++ return TARGET_EFAULT; ++ } else pout = NULL; ++ ++ /* Shortens the count to valid pages only. ++ * TODO: check, see translate_all.c */ ++ __attribute__((unused)) const abi_long req_count = count; ++ count = valid_len(buf, count, PAGE_READ|PAGE_WRITE); ++#ifdef DEBUG_LENIENT_LENGTHS ++ if (count < req_count) ++ fprintf(stderr, "FOR_CGC: Pre-shortening random() count=%d to %d\n", req_count, count); ++#endif ++ ++ for (i = 0; i < count; i += sizeof(randval)) { ++ _Static_assert(RAND_MAX >= INT16_MAX, "I rely on RAND_MAX giving at least 16 random bits"); ++ randval = 0x4141; ++ if (seed_passed) ++ randval = rand() & 0xFFFFu; ++ size = ((count - i) < sizeof(randval)) ? (count - i) : sizeof(randval); ++ if (size == 1) { ++ ret = put_user_u8((uint8_t) randval, buf + i); ++ } else if (size == 2) { ++ ret = put_user_u16(randval, buf + i); + } else { +- target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level); +- } +- target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type); +- target_cmsg->cmsg_len = tswapal(TARGET_CMSG_LEN(len)); +- +- switch (cmsg->cmsg_level) { +- case SOL_SOCKET: +- switch (cmsg->cmsg_type) { +- case SCM_RIGHTS: +- { +- int *fd = (int *)data; +- int *target_fd = (int *)target_data; +- int i, numfds = len / sizeof(int); +- +- for (i = 0; i < numfds; i++) +- target_fd[i] = tswap32(fd[i]); +- break; +- } +- case SO_TIMESTAMP: +- { +- struct timeval *tv = (struct timeval *)data; +- struct target_timeval *target_tv = +- (struct target_timeval *)target_data; +- +- if (len != sizeof(struct timeval)) +- goto unimplemented; +- +- /* copy struct timeval to target */ +- target_tv->tv_sec = tswapal(tv->tv_sec); +- target_tv->tv_usec = tswapal(tv->tv_usec); +- break; +- } +- case SCM_CREDENTIALS: +- { +- struct ucred *cred = (struct ucred *)data; +- struct target_ucred *target_cred = +- (struct target_ucred *)target_data; +- +- __put_user(cred->pid, &target_cred->pid); +- __put_user(cred->uid, &target_cred->uid); +- __put_user(cred->gid, &target_cred->gid); +- break; +- } +- default: +- goto unimplemented; +- } +- break; +- +- default: +- unimplemented: +- gemu_log("Unsupported ancillary data: %d/%d\n", +- cmsg->cmsg_level, cmsg->cmsg_type); +- memcpy(target_data, data, len); ++ fprintf(stderr, "qemu: INTERNAL ERROR: I can only write 8 or 16 bits at a time! (asked for %zd)", size); ++ exit(-37); + } ++ if (ret) ++ return ret; ++ } + +- cmsg = CMSG_NXTHDR(msgh, cmsg); +- target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg); ++ if (pout != NULL) { ++ __put_user(count, pout); ++ unlock_user(pout, p_rnd_out, 4); + } +- unlock_user(target_cmsg, target_cmsg_addr, space); +- the_end: +- target_msgh->msg_controllen = tswapal(space); + return 0; + } + +-/* do_setsockopt() Must return target values and target errnos. */ +-static abi_long do_setsockopt(int sockfd, int level, int optname, +- abi_ulong optval_addr, socklen_t optlen) ++static abi_long do_allocate(abi_ulong len, abi_ulong exec, abi_ulong p_addr) + { ++ int prot = PROT_READ | PROT_WRITE; ++ abi_ulong *p; + abi_long ret; +- int val; +- struct ip_mreqn *ip_mreq; +- struct ip_mreq_source *ip_mreq_source; +- +- switch(level) { +- case SOL_TCP: +- /* TCP options all take an 'int' value. */ +- if (optlen < sizeof(uint32_t)) +- return -TARGET_EINVAL; +- +- if (get_user_u32(val, optval_addr)) +- return -TARGET_EFAULT; +- ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val))); +- break; +- case SOL_IP: +- switch(optname) { +- case IP_TOS: +- case IP_TTL: +- case IP_HDRINCL: +- case IP_ROUTER_ALERT: +- case IP_RECVOPTS: +- case IP_RETOPTS: +- case IP_PKTINFO: +- case IP_MTU_DISCOVER: +- case IP_RECVERR: +- case IP_RECVTOS: +-#ifdef IP_FREEBIND +- case IP_FREEBIND: +-#endif +- case IP_MULTICAST_TTL: +- case IP_MULTICAST_LOOP: +- val = 0; +- if (optlen >= sizeof(uint32_t)) { +- if (get_user_u32(val, optval_addr)) +- return -TARGET_EFAULT; +- } else if (optlen >= 1) { +- if (get_user_u8(val, optval_addr)) +- return -TARGET_EFAULT; +- } +- ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val))); +- break; +- case IP_ADD_MEMBERSHIP: +- case IP_DROP_MEMBERSHIP: +- if (optlen < sizeof (struct target_ip_mreq) || +- optlen > sizeof (struct target_ip_mreqn)) +- return -TARGET_EINVAL; +- +- ip_mreq = (struct ip_mreqn *) alloca(optlen); +- target_to_host_ip_mreq(ip_mreq, optval_addr, optlen); +- ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq, optlen)); +- break; +- +- case IP_BLOCK_SOURCE: +- case IP_UNBLOCK_SOURCE: +- case IP_ADD_SOURCE_MEMBERSHIP: +- case IP_DROP_SOURCE_MEMBERSHIP: +- if (optlen != sizeof (struct target_ip_mreq_source)) +- return -TARGET_EINVAL; +- +- ip_mreq_source = lock_user(VERIFY_READ, optval_addr, optlen, 1); +- ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq_source, optlen)); +- unlock_user (ip_mreq_source, optval_addr, 0); +- break; +- +- default: +- goto unimplemented; +- } +- break; +- case SOL_IPV6: +- switch (optname) { +- case IPV6_MTU_DISCOVER: +- case IPV6_MTU: +- case IPV6_V6ONLY: +- case IPV6_RECVPKTINFO: +- val = 0; +- if (optlen < sizeof(uint32_t)) { +- return -TARGET_EINVAL; +- } +- if (get_user_u32(val, optval_addr)) { +- return -TARGET_EFAULT; +- } +- ret = get_errno(setsockopt(sockfd, level, optname, +- &val, sizeof(val))); +- break; +- default: +- goto unimplemented; +- } +- break; +- case SOL_RAW: +- switch (optname) { +- case ICMP_FILTER: +- /* struct icmp_filter takes an u32 value */ +- if (optlen < sizeof(uint32_t)) { +- return -TARGET_EINVAL; +- } +- +- if (get_user_u32(val, optval_addr)) { +- return -TARGET_EFAULT; +- } +- ret = get_errno(setsockopt(sockfd, level, optname, +- &val, sizeof(val))); +- break; +- +- default: +- goto unimplemented; +- } +- break; +- case TARGET_SOL_SOCKET: +- switch (optname) { +- case TARGET_SO_RCVTIMEO: +- { +- struct timeval tv; +- +- optname = SO_RCVTIMEO; + +-set_timeout: +- if (optlen != sizeof(struct target_timeval)) { +- return -TARGET_EINVAL; +- } ++ if (len == 0) // ABI-specified, vagrant returns this before EFAULT ++ return TARGET_EINVAL; + +- if (copy_from_user_timeval(&tv, optval_addr)) { +- return -TARGET_EFAULT; +- } ++ if (exec) ++ prot |= PROT_EXEC; + +- ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, +- &tv, sizeof(tv))); +- return ret; +- } +- case TARGET_SO_SNDTIMEO: +- optname = SO_SNDTIMEO; +- goto set_timeout; +- case TARGET_SO_ATTACH_FILTER: +- { +- struct target_sock_fprog *tfprog; +- struct target_sock_filter *tfilter; +- struct sock_fprog fprog; +- struct sock_filter *filter; +- int i; ++ if (p_addr != 0) { ++ if (!(p = lock_user(VERIFY_WRITE, p_addr, 4, 0))) ++ return TARGET_EFAULT; ++ } else p = NULL; /* Believe it or not, binfmt_cgc allows this */ + +- if (optlen != sizeof(*tfprog)) { +- return -TARGET_EINVAL; +- } +- if (!lock_user_struct(VERIFY_READ, tfprog, optval_addr, 0)) { +- return -TARGET_EFAULT; +- } +- if (!lock_user_struct(VERIFY_READ, tfilter, +- tswapal(tfprog->filter), 0)) { +- unlock_user_struct(tfprog, optval_addr, 1); +- return -TARGET_EFAULT; +- } ++ ret = 0; ++ abi_ulong chosen = 0; ++ abi_ulong sinkhole_chosen = 0; ++ abi_ulong aligned_len = ((len + 0xfff) / 0x1000) * 0x1000; + +- fprog.len = tswap16(tfprog->len); +- filter = malloc(fprog.len * sizeof(*filter)); +- if (filter == NULL) { +- unlock_user_struct(tfilter, tfprog->filter, 1); +- unlock_user_struct(tfprog, optval_addr, 1); +- return -TARGET_ENOMEM; +- } +- for (i = 0; i < fprog.len; i++) { +- filter[i].code = tswap16(tfilter[i].code); +- filter[i].jt = tfilter[i].jt; +- filter[i].jf = tfilter[i].jf; +- filter[i].k = tswap32(tfilter[i].k); +- } +- fprog.filter = filter; ++ /* check sinkholes */ ++ chosen = sinkhole_chosen = get_max_sinkhole(aligned_len); ++ if (!chosen) ++ chosen = mmap_next_start - aligned_len; + +- ret = get_errno(setsockopt(sockfd, SOL_SOCKET, +- SO_ATTACH_FILTER, &fprog, sizeof(fprog))); +- free(filter); ++ abi_ulong mmap_ret = target_mmap((abi_ulong)chosen, aligned_len, prot, MAP_ANONYMOUS | MAP_PRIVATE| MAP_FIXED, -1, 0); ++ if (mmap_ret == -1) ++ return get_errno(mmap_ret); ++ if (mmap_ret == 0) ++ return host_to_target_errno(errno); + +- unlock_user_struct(tfilter, tfprog->filter, 1); +- unlock_user_struct(tfprog, optval_addr, 1); +- return ret; +- } +- case TARGET_SO_BINDTODEVICE: +- { +- char *dev_ifname, *addr_ifname; +- +- if (optlen > IFNAMSIZ - 1) { +- optlen = IFNAMSIZ - 1; +- } +- dev_ifname = lock_user(VERIFY_READ, optval_addr, optlen, 1); +- if (!dev_ifname) { +- return -TARGET_EFAULT; +- } +- optname = SO_BINDTODEVICE; +- addr_ifname = alloca(IFNAMSIZ); +- memcpy(addr_ifname, dev_ifname, optlen); +- addr_ifname[optlen] = 0; +- ret = get_errno(setsockopt(sockfd, level, optname, addr_ifname, optlen)); +- unlock_user (dev_ifname, optval_addr, 0); +- return ret; +- } +- /* Options with 'int' argument. */ +- case TARGET_SO_DEBUG: +- optname = SO_DEBUG; +- break; +- case TARGET_SO_REUSEADDR: +- optname = SO_REUSEADDR; +- break; +- case TARGET_SO_TYPE: +- optname = SO_TYPE; +- break; +- case TARGET_SO_ERROR: +- optname = SO_ERROR; +- break; +- case TARGET_SO_DONTROUTE: +- optname = SO_DONTROUTE; +- break; +- case TARGET_SO_BROADCAST: +- optname = SO_BROADCAST; +- break; +- case TARGET_SO_SNDBUF: +- optname = SO_SNDBUF; +- break; +- case TARGET_SO_SNDBUFFORCE: +- optname = SO_SNDBUFFORCE; +- break; +- case TARGET_SO_RCVBUF: +- optname = SO_RCVBUF; +- break; +- case TARGET_SO_RCVBUFFORCE: +- optname = SO_RCVBUFFORCE; +- break; +- case TARGET_SO_KEEPALIVE: +- optname = SO_KEEPALIVE; +- break; +- case TARGET_SO_OOBINLINE: +- optname = SO_OOBINLINE; +- break; +- case TARGET_SO_NO_CHECK: +- optname = SO_NO_CHECK; +- break; +- case TARGET_SO_PRIORITY: +- optname = SO_PRIORITY; +- break; +-#ifdef SO_BSDCOMPAT +- case TARGET_SO_BSDCOMPAT: +- optname = SO_BSDCOMPAT; +- break; +-#endif +- case TARGET_SO_PASSCRED: +- optname = SO_PASSCRED; +- break; +- case TARGET_SO_PASSSEC: +- optname = SO_PASSSEC; +- break; +- case TARGET_SO_TIMESTAMP: +- optname = SO_TIMESTAMP; +- break; +- case TARGET_SO_RCVLOWAT: +- optname = SO_RCVLOWAT; +- break; +- break; +- default: +- goto unimplemented; +- } +- if (optlen < sizeof(uint32_t)) +- return -TARGET_EINVAL; ++ if (!sinkhole_chosen) ++ mmap_next_start = chosen; + +- if (get_user_u32(val, optval_addr)) +- return -TARGET_EFAULT; +- ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val))); +- break; +- default: +- unimplemented: +- gemu_log("Unsupported setsockopt level=%d optname=%d\n", level, optname); +- ret = -TARGET_ENOPROTOOPT; ++ if (p != NULL) { ++ __put_user(mmap_ret, p); ++ unlock_user(p, p_addr, 4); + } +- return ret; +-} +- +-/* do_getsockopt() Must return target values and target errnos. */ +-static abi_long do_getsockopt(int sockfd, int level, int optname, +- abi_ulong optval_addr, abi_ulong optlen) +-{ +- abi_long ret; +- int len, val; +- socklen_t lv; +- +- switch(level) { +- case TARGET_SOL_SOCKET: +- level = SOL_SOCKET; +- switch (optname) { +- /* These don't just return a single integer */ +- case TARGET_SO_LINGER: +- case TARGET_SO_RCVTIMEO: +- case TARGET_SO_SNDTIMEO: +- case TARGET_SO_PEERNAME: +- goto unimplemented; +- case TARGET_SO_PEERCRED: { +- struct ucred cr; +- socklen_t crlen; +- struct target_ucred *tcr; +- +- if (get_user_u32(len, optlen)) { +- return -TARGET_EFAULT; +- } +- if (len < 0) { +- return -TARGET_EINVAL; +- } + +- crlen = sizeof(cr); +- ret = get_errno(getsockopt(sockfd, level, SO_PEERCRED, +- &cr, &crlen)); +- if (ret < 0) { +- return ret; +- } +- if (len > crlen) { +- len = crlen; +- } +- if (!lock_user_struct(VERIFY_WRITE, tcr, optval_addr, 0)) { +- return -TARGET_EFAULT; +- } +- __put_user(cr.pid, &tcr->pid); +- __put_user(cr.uid, &tcr->uid); +- __put_user(cr.gid, &tcr->gid); +- unlock_user_struct(tcr, optval_addr, 1); +- if (put_user_u32(len, optlen)) { +- return -TARGET_EFAULT; +- } +- break; +- } +- /* Options with 'int' argument. */ +- case TARGET_SO_DEBUG: +- optname = SO_DEBUG; +- goto int_case; +- case TARGET_SO_REUSEADDR: +- optname = SO_REUSEADDR; +- goto int_case; +- case TARGET_SO_TYPE: +- optname = SO_TYPE; +- goto int_case; +- case TARGET_SO_ERROR: +- optname = SO_ERROR; +- goto int_case; +- case TARGET_SO_DONTROUTE: +- optname = SO_DONTROUTE; +- goto int_case; +- case TARGET_SO_BROADCAST: +- optname = SO_BROADCAST; +- goto int_case; +- case TARGET_SO_SNDBUF: +- optname = SO_SNDBUF; +- goto int_case; +- case TARGET_SO_RCVBUF: +- optname = SO_RCVBUF; +- goto int_case; +- case TARGET_SO_KEEPALIVE: +- optname = SO_KEEPALIVE; +- goto int_case; +- case TARGET_SO_OOBINLINE: +- optname = SO_OOBINLINE; +- goto int_case; +- case TARGET_SO_NO_CHECK: +- optname = SO_NO_CHECK; +- goto int_case; +- case TARGET_SO_PRIORITY: +- optname = SO_PRIORITY; +- goto int_case; +-#ifdef SO_BSDCOMPAT +- case TARGET_SO_BSDCOMPAT: +- optname = SO_BSDCOMPAT; +- goto int_case; +-#endif +- case TARGET_SO_PASSCRED: +- optname = SO_PASSCRED; +- goto int_case; +- case TARGET_SO_TIMESTAMP: +- optname = SO_TIMESTAMP; +- goto int_case; +- case TARGET_SO_RCVLOWAT: +- optname = SO_RCVLOWAT; +- goto int_case; +- case TARGET_SO_ACCEPTCONN: +- optname = SO_ACCEPTCONN; +- goto int_case; +- default: +- goto int_case; +- } +- break; +- case SOL_TCP: +- /* TCP options all take an 'int' value. */ +- int_case: +- if (get_user_u32(len, optlen)) +- return -TARGET_EFAULT; +- if (len < 0) +- return -TARGET_EINVAL; +- lv = sizeof(lv); +- ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv)); +- if (ret < 0) +- return ret; +- if (optname == SO_TYPE) { +- val = host_to_target_sock_type(val); +- } +- if (len > lv) +- len = lv; +- if (len == 4) { +- if (put_user_u32(val, optval_addr)) +- return -TARGET_EFAULT; +- } else { +- if (put_user_u8(val, optval_addr)) +- return -TARGET_EFAULT; +- } +- if (put_user_u32(len, optlen)) +- return -TARGET_EFAULT; +- break; +- case SOL_IP: +- switch(optname) { +- case IP_TOS: +- case IP_TTL: +- case IP_HDRINCL: +- case IP_ROUTER_ALERT: +- case IP_RECVOPTS: +- case IP_RETOPTS: +- case IP_PKTINFO: +- case IP_MTU_DISCOVER: +- case IP_RECVERR: +- case IP_RECVTOS: +-#ifdef IP_FREEBIND +- case IP_FREEBIND: +-#endif +- case IP_MULTICAST_TTL: +- case IP_MULTICAST_LOOP: +- if (get_user_u32(len, optlen)) +- return -TARGET_EFAULT; +- if (len < 0) +- return -TARGET_EINVAL; +- lv = sizeof(lv); +- ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv)); +- if (ret < 0) +- return ret; +- if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) { +- len = 1; +- if (put_user_u32(len, optlen) +- || put_user_u8(val, optval_addr)) +- return -TARGET_EFAULT; +- } else { +- if (len > sizeof(int)) +- len = sizeof(int); +- if (put_user_u32(len, optlen) +- || put_user_u32(val, optval_addr)) +- return -TARGET_EFAULT; +- } +- break; +- default: +- ret = -TARGET_ENOPROTOOPT; +- break; +- } +- break; +- default: +- unimplemented: +- gemu_log("getsockopt level=%d optname=%d not yet supported\n", +- level, optname); +- ret = -TARGET_EOPNOTSUPP; +- break; +- } + return ret; + } + +-static struct iovec *lock_iovec(int type, abi_ulong target_addr, +- int count, int copy) ++static abi_long do_deallocate(abi_ulong start, abi_ulong len) + { +- struct target_iovec *target_vec; +- struct iovec *vec; +- abi_ulong total_len, max_len; +- int i; +- int err = 0; +- bool bad_address = false; +- +- if (count == 0) { +- errno = 0; +- return NULL; +- } +- if (count < 0 || count > IOV_MAX) { +- errno = EINVAL; +- return NULL; +- } +- +- vec = calloc(count, sizeof(struct iovec)); +- if (vec == NULL) { +- errno = ENOMEM; +- return NULL; +- } +- +- target_vec = lock_user(VERIFY_READ, target_addr, +- count * sizeof(struct target_iovec), 1); +- if (target_vec == NULL) { +- err = EFAULT; +- goto fail2; +- } +- +- /* ??? If host page size > target page size, this will result in a +- value larger than what we can actually support. */ +- max_len = 0x7fffffff & TARGET_PAGE_MASK; +- total_len = 0; +- +- for (i = 0; i < count; i++) { +- abi_ulong base = tswapal(target_vec[i].iov_base); +- abi_long len = tswapal(target_vec[i].iov_len); +- +- if (len < 0) { +- err = EINVAL; +- goto fail; +- } else if (len == 0) { +- /* Zero length pointer is ignored. */ +- vec[i].iov_base = 0; +- } else { +- vec[i].iov_base = lock_user(type, base, len, copy); +- /* If the first buffer pointer is bad, this is a fault. But +- * subsequent bad buffers will result in a partial write; this +- * is realized by filling the vector with null pointers and +- * zero lengths. */ +- if (!vec[i].iov_base) { +- if (i == 0) { +- err = EFAULT; +- goto fail; +- } else { +- bad_address = true; +- } +- } +- if (bad_address) { +- len = 0; +- } +- if (len > max_len - total_len) { +- len = max_len - total_len; +- } +- } +- vec[i].iov_len = len; +- total_len += len; +- } ++ abi_long ret; ++ abi_ulong aligned_len = ((len + 0xfff) / 0x1000) * 0x1000; ++ abi_ulong allowed_length = 0; + +- unlock_user(target_vec, target_addr, 0); +- return vec; ++ // ABI-specified: EINVAL on misaligned || len == 0 ++ if (((start % 4096) != 0) || (len == 0)) ++ return TARGET_EINVAL; ++ if ((start + aligned_len) > reserved_va) // TODO: "outside the valid address range"... ++ return TARGET_EINVAL; + +- fail: +- while (--i >= 0) { +- if (tswapal(target_vec[i].iov_len) > 0) { +- unlock_user(vec[i].iov_base, tswapal(target_vec[i].iov_base), 0); +- } ++ // HACK! check to see if the page is mapped, if not deallocate fails ++ while ((lock_user(VERIFY_WRITE, start, allowed_length + 0x1000, 0)) && allowed_length < aligned_len) { ++ allowed_length += 0x1000; + } +- unlock_user(target_vec, target_addr, 0); +- fail2: +- free(vec); +- errno = err; +- return NULL; +-} + +-static void unlock_iovec(struct iovec *vec, abi_ulong target_addr, +- int count, int copy) +-{ +- struct target_iovec *target_vec; +- int i; +- +- target_vec = lock_user(VERIFY_READ, target_addr, +- count * sizeof(struct target_iovec), 1); +- if (target_vec) { +- for (i = 0; i < count; i++) { +- abi_ulong base = tswapal(target_vec[i].iov_base); +- abi_long len = tswapal(target_vec[i].iov_len); +- if (len < 0) { +- break; +- } +- unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0); +- } +- unlock_user(target_vec, target_addr, 0); ++ if (allowed_length == 0) { ++ return 0; // Apparently that's what the ABI does + } + +- free(vec); +-} +- +-static inline int target_to_host_sock_type(int *type) +-{ +- int host_type = 0; +- int target_type = *type; +- +- switch (target_type & TARGET_SOCK_TYPE_MASK) { +- case TARGET_SOCK_DGRAM: +- host_type = SOCK_DGRAM; +- break; +- case TARGET_SOCK_STREAM: +- host_type = SOCK_STREAM; +- break; +- default: +- host_type = target_type & TARGET_SOCK_TYPE_MASK; +- break; +- } +- if (target_type & TARGET_SOCK_CLOEXEC) { +-#if defined(SOCK_CLOEXEC) +- host_type |= SOCK_CLOEXEC; +-#else +- return -TARGET_EINVAL; +-#endif +- } +- if (target_type & TARGET_SOCK_NONBLOCK) { +-#if defined(SOCK_NONBLOCK) +- host_type |= SOCK_NONBLOCK; +-#elif !defined(O_NONBLOCK) +- return -TARGET_EINVAL; +-#endif +- } +- *type = host_type; +- return 0; +-} ++ aligned_len = allowed_length; + +-/* Try to emulate socket type flags after socket creation. */ +-static int sock_flags_fixup(int fd, int target_type) +-{ +-#if !defined(SOCK_NONBLOCK) && defined(O_NONBLOCK) +- if (target_type & TARGET_SOCK_NONBLOCK) { +- int flags = fcntl(fd, F_GETFL); +- if (fcntl(fd, F_SETFL, O_NONBLOCK | flags) == -1) { +- close(fd); +- return -TARGET_EINVAL; +- } +- } +-#endif +- return fd; +-} ++ // No deallocating the flag page! (check from binfmt_cgc.c) ++ if (!((start + aligned_len) <= 0x4347c000 || start >= (0x4347c000 + 4096))) ++ return TARGET_EINVAL; + +-/* do_socket() Must return target values and target errnos. */ +-static abi_long do_socket(int domain, int type, int protocol) +-{ +- int target_type = type; +- int ret; ++ ret = target_munmap(start, aligned_len); + +- ret = target_to_host_sock_type(&type); +- if (ret) { +- return ret; +- } ++ /* target_munmap returns either 0 or the errno * -1 */ ++ if (ret < 0) ++ return host_to_target_errno(ret * -1); + +- if (domain == PF_NETLINK) +- return -TARGET_EAFNOSUPPORT; +- ret = get_errno(socket(domain, type, protocol)); +- if (ret >= 0) { +- ret = sock_flags_fixup(ret, target_type); +- } ++ if (start == mmap_next_start) ++ mmap_next_start += aligned_len; ++ else /* add a sinkhole */ ++ add_sinkhole(start, aligned_len); ++ + return ret; + } + +-/* do_bind() Must return target values and target errnos. */ +-static abi_long do_bind(int sockfd, abi_ulong target_addr, +- socklen_t addrlen) ++#define USEC_PER_SEC 1000000L ++static abi_long do_fdwait(abi_int n, abi_ulong rfd_addr, abi_ulong wfd_addr, abi_ulong target_tv_addr, abi_ulong p_readyfds) + { +- void *addr; ++ fd_set rfds, wfds; ++ fd_set *rfds_ptr = NULL, *wfds_ptr = NULL; ++ struct timeval tv, *tv_ptr; + abi_long ret; + +- if ((int)addrlen < 0) { +- return -TARGET_EINVAL; +- } +- +- addr = alloca(addrlen+1); +- +- ret = target_to_host_sockaddr(addr, target_addr, addrlen); +- if (ret) +- return ret; +- +- return get_errno(bind(sockfd, addr, addrlen)); +-} ++ abi_ulong *pready; ++ if (p_readyfds != 0) { /* Believe it or not, binfmt_cgc allows this */ ++ if (!(pready = lock_user(VERIFY_WRITE, p_readyfds, 4, 0))) ++ return TARGET_EFAULT; ++ } else pready = NULL; + +-/* do_connect() Must return target values and target errnos. */ +-static abi_long do_connect(int sockfd, abi_ulong target_addr, +- socklen_t addrlen) +-{ +- void *addr; +- abi_long ret; + +- if ((int)addrlen < 0) { +- return -TARGET_EINVAL; ++ if (target_tv_addr) { ++ if (copy_from_user_timeval(&tv, target_tv_addr)) ++ return TARGET_EFAULT; ++ tv_ptr = &tv; ++ tv.tv_sec = tv.tv_sec + (tv.tv_usec / USEC_PER_SEC); ++ tv.tv_usec %= USEC_PER_SEC; ++ tv.tv_usec -= tv.tv_usec % 10000; /* gate to 0.01s */ ++ } else { ++ tv_ptr = NULL; + } +- +- addr = alloca(addrlen+1); +- +- ret = target_to_host_sockaddr(addr, target_addr, addrlen); +- if (ret) ++ ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n); ++ if (ret) { + return ret; +- +- return get_errno(connect(sockfd, addr, addrlen)); +-} +- +-/* do_sendrecvmsg_locked() Must return target values and target errnos. */ +-static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp, +- int flags, int send) +-{ +- abi_long ret, len; +- struct msghdr msg; +- int count; +- struct iovec *vec; +- abi_ulong target_vec; +- +- if (msgp->msg_name) { +- msg.msg_namelen = tswap32(msgp->msg_namelen); +- msg.msg_name = alloca(msg.msg_namelen+1); +- ret = target_to_host_sockaddr(msg.msg_name, tswapal(msgp->msg_name), +- msg.msg_namelen); +- if (ret) { +- goto out2; +- } +- } else { +- msg.msg_name = NULL; +- msg.msg_namelen = 0; + } +- msg.msg_controllen = 2 * tswapal(msgp->msg_controllen); +- msg.msg_control = alloca(msg.msg_controllen); +- msg.msg_flags = tswap32(msgp->msg_flags); +- +- count = tswapal(msgp->msg_iovlen); +- target_vec = tswapal(msgp->msg_iov); +- vec = lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, +- target_vec, count, send); +- if (vec == NULL) { +- ret = -host_to_target_errno(errno); +- goto out2; ++ ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n); ++ if (ret) { ++ return ret; + } +- msg.msg_iovlen = count; +- msg.msg_iov = vec; + +- if (send) { +- ret = target_to_host_cmsg(&msg, msgp); +- if (ret == 0) +- ret = get_errno(sendmsg(fd, &msg, flags)); +- } else { +- ret = get_errno(recvmsg(fd, &msg, flags)); +- if (!is_error(ret)) { +- len = ret; +- ret = host_to_target_cmsg(msgp, &msg); +- if (!is_error(ret)) { +- msgp->msg_namelen = tswap32(msg.msg_namelen); +- if (msg.msg_name != NULL) { +- ret = host_to_target_sockaddr(tswapal(msgp->msg_name), +- msg.msg_name, msg.msg_namelen); +- if (ret) { +- goto out; +- } +- } ++ /* XXX: Linux auto-adjusts the timeout parameter unless STICKY_TIMEOUTS is set: ++ * CGC binaries have that, but we don't need it (we just don't copy tv back). */ ++ do { ++ ret = select(n, rfds_ptr, wfds_ptr, NULL, tv_ptr); ++ } while ((ret == -1) && (errno == EINTR)); ++ if (ret == -1) ++ return get_errno(ret); + +- ret = len; +- } +- } ++ if (is_error(ret)) { ++ fprintf(stderr, "qemu: INTERNAL ERROR: select returned an error value != -1 ("TARGET_ABI_FMT_ld") !", ret); ++ exit(-39); + } + +-out: +- unlock_iovec(vec, target_vec, count, !send); +-out2: +- return ret; +-} +- +-static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg, +- int flags, int send) +-{ +- abi_long ret; +- struct target_msghdr *msgp; ++ if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n)) ++ return TARGET_EFAULT; ++ if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n)) ++ return TARGET_EFAULT; + +- if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE, +- msgp, +- target_msg, +- send ? 1 : 0)) { +- return -TARGET_EFAULT; ++ if (pready != NULL) { ++ __put_user(ret, pready); ++ unlock_user(pready, p_readyfds, 4); + } +- ret = do_sendrecvmsg_locked(fd, msgp, flags, send); +- unlock_user_struct(msgp, target_msg, send ? 0 : 1); +- return ret; ++ return 0; + } + +-#ifdef TARGET_NR_sendmmsg +-/* We don't rely on the C library to have sendmmsg/recvmmsg support, +- * so it might not have this *mmsg-specific flag either. +- */ +-#ifndef MSG_WAITFORONE +-#define MSG_WAITFORONE 0x10000 +-#endif + +-static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec, +- unsigned int vlen, unsigned int flags, +- int send) ++/* do_syscall() should always have a single exit point at the end so ++ that actions, such as logging of syscall results, can be performed. ++ All errnos that do_syscall() returns must be -TARGET_. */ ++abi_long do_syscall(void *cpu_env, int num, abi_long arg1, ++ abi_long arg2, abi_long arg3, abi_long arg4, ++ abi_long arg5, abi_long arg6, abi_long arg7, ++ abi_long arg8) + { +- struct target_mmsghdr *mmsgp; +- abi_long ret = 0; +- int i; +- +- if (vlen > UIO_MAXIOV) { +- vlen = UIO_MAXIOV; +- } +- +- mmsgp = lock_user(VERIFY_WRITE, target_msgvec, sizeof(*mmsgp) * vlen, 1); +- if (!mmsgp) { +- return -TARGET_EFAULT; +- } +- +- for (i = 0; i < vlen; i++) { +- ret = do_sendrecvmsg_locked(fd, &mmsgp[i].msg_hdr, flags, send); +- if (is_error(ret)) { +- break; +- } +- mmsgp[i].msg_len = tswap32(ret); +- /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */ +- if (flags & MSG_WAITFORONE) { +- flags |= MSG_DONTWAIT; +- } +- } +- +- unlock_user(mmsgp, target_msgvec, sizeof(*mmsgp) * i); ++ /* CPUState *cpu = ENV_GET_CPU(cpu_env); */ ++ abi_long ret; + +- /* Return number of datagrams sent if we sent any at all; +- * otherwise return the error. +- */ +- if (i) { +- return i; +- } +- return ret; +-} ++#ifdef DEBUG ++ gemu_log("syscall %d", num); + #endif ++ if(do_strace) ++ print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6); + +-/* If we don't have a system accept4() then just call accept. +- * The callsites to do_accept4() will ensure that they don't +- * pass a non-zero flags argument in this config. +- */ +-#ifndef CONFIG_ACCEPT4 +-static inline int accept4(int sockfd, struct sockaddr *addr, +- socklen_t *addrlen, int flags) +-{ +- assert(flags == 0); +- return accept(sockfd, addr, addrlen); +-} ++ switch(num) { ++ case TARGET_NR_receive: ++#if defined(TRACER) || defined(AFL) ++ ret = do_receive(cpu_env, arg1, arg2, arg3, arg4); ++#else ++ ret = do_receive(arg1, arg2, arg3, arg4); + #endif ++ break; ++ case TARGET_NR_transmit: ++ ret = do_transmit(arg1, arg2, arg3, arg4); ++ break; + +-/* do_accept4() Must return target values and target errnos. */ +-static abi_long do_accept4(int fd, abi_ulong target_addr, +- abi_ulong target_addrlen_addr, int flags) +-{ +- socklen_t addrlen; +- void *addr; +- abi_long ret; +- int host_flags; +- +- host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl); +- +- if (target_addr == 0) { +- return get_errno(accept4(fd, NULL, NULL, host_flags)); +- } +- +- /* linux returns EINVAL if addrlen pointer is invalid */ +- if (get_user_u32(addrlen, target_addrlen_addr)) +- return -TARGET_EINVAL; +- +- if ((int)addrlen < 0) { +- return -TARGET_EINVAL; +- } +- +- if (!access_ok(VERIFY_WRITE, target_addr, addrlen)) +- return -TARGET_EINVAL; +- +- addr = alloca(addrlen); +- +- ret = get_errno(accept4(fd, addr, &addrlen, host_flags)); +- if (!is_error(ret)) { +- host_to_target_sockaddr(target_addr, addr, addrlen); +- if (put_user_u32(addrlen, target_addrlen_addr)) +- ret = -TARGET_EFAULT; +- } +- return ret; +-} +- +-/* do_getpeername() Must return target values and target errnos. */ +-static abi_long do_getpeername(int fd, abi_ulong target_addr, +- abi_ulong target_addrlen_addr) +-{ +- socklen_t addrlen; +- void *addr; +- abi_long ret; +- +- if (get_user_u32(addrlen, target_addrlen_addr)) +- return -TARGET_EFAULT; +- +- if ((int)addrlen < 0) { +- return -TARGET_EINVAL; +- } ++ case TARGET_NR_fdwait: ++ ret = do_fdwait(arg1, arg2, arg3, arg4, arg5); ++ break; + +- if (!access_ok(VERIFY_WRITE, target_addr, addrlen)) +- return -TARGET_EFAULT; + +- addr = alloca(addrlen); ++ case TARGET_NR_allocate: ++ ret = do_allocate(arg1, arg2, arg3); ++ break; + +- ret = get_errno(getpeername(fd, addr, &addrlen)); +- if (!is_error(ret)) { +- host_to_target_sockaddr(target_addr, addr, addrlen); +- if (put_user_u32(addrlen, target_addrlen_addr)) +- ret = -TARGET_EFAULT; +- } +- return ret; +-} ++ case TARGET_NR_deallocate: ++ ret = do_deallocate(arg1, arg2); ++ break; + +-/* do_getsockname() Must return target values and target errnos. */ +-static abi_long do_getsockname(int fd, abi_ulong target_addr, +- abi_ulong target_addrlen_addr) +-{ +- socklen_t addrlen; +- void *addr; +- abi_long ret; + +- if (get_user_u32(addrlen, target_addrlen_addr)) +- return -TARGET_EFAULT; ++ case TARGET_NR_terminate: ++#ifdef TARGET_GPROF ++ _mcleanup(); ++#endif ++ gdb_exit(cpu_env, arg1); ++ ret = get_errno(exit_group(arg1)); ++ break; + +- if ((int)addrlen < 0) { +- return -TARGET_EINVAL; +- } + +- if (!access_ok(VERIFY_WRITE, target_addr, addrlen)) +- return -TARGET_EFAULT; ++ case TARGET_NR_random: ++ ret = do_random(arg1, arg2, arg3); ++ break; + +- addr = alloca(addrlen); + +- ret = get_errno(getsockname(fd, addr, &addrlen)); +- if (!is_error(ret)) { +- host_to_target_sockaddr(target_addr, addr, addrlen); +- if (put_user_u32(addrlen, target_addrlen_addr)) +- ret = -TARGET_EFAULT; ++ default: ++ gemu_log("qemu: Unsupported syscall: %d\n", num); ++ ret = TARGET_ENOSYS; ++ break; + } +- return ret; +-} +- +-/* do_socketpair() Must return target values and target errnos. */ +-static abi_long do_socketpair(int domain, int type, int protocol, +- abi_ulong target_tab_addr) +-{ +- int tab[2]; +- abi_long ret; +- +- target_to_host_sock_type(&type); +- +- ret = get_errno(socketpair(domain, type, protocol, tab)); +- if (!is_error(ret)) { +- if (put_user_s32(tab[0], target_tab_addr) +- || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0]))) +- ret = -TARGET_EFAULT; ++#ifdef DEBUG ++ gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret); ++#endif ++ if(do_strace) ++ print_syscall_ret(num, ret); ++ if (!((ret >= 0) && (ret <= 6))) { /* CGC syscalls return either 0 or an error */ ++ fprintf(stderr, "qemu: INTERNAL ERROR: syscall %d tried to return %d, but all CGC syscall return either 0 or one of the CGC_Exxx (positive) values.\n", num, ret); ++ exit(-33); + } + return ret; + } +- +-/* do_sendto() Must return target values and target errnos. */ +-static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags, +- abi_ulong target_addr, socklen_t addrlen) +-{ +- void *addr; +- void *host_msg; +- abi_long ret; +- +- if ((int)addrlen < 0) { +- return -TARGET_EINVAL; +- } +- +- host_msg = lock_user(VERIFY_READ, msg, len, 1); +- if (!host_msg) +- return -TARGET_EFAULT; +- if (target_addr) { +- addr = alloca(addrlen+1); +- ret = target_to_host_sockaddr(addr, target_addr, addrlen); +- if (ret) { +- unlock_user(host_msg, msg, 0); +- return ret; +- } +- ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen)); +- } else { +- ret = get_errno(send(fd, host_msg, len, flags)); +- } +- unlock_user(host_msg, msg, 0); +- return ret; +-} +- +-/* do_recvfrom() Must return target values and target errnos. */ +-static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags, +- abi_ulong target_addr, +- abi_ulong target_addrlen) +-{ +- socklen_t addrlen; +- void *addr; +- void *host_msg; +- abi_long ret; +- +- host_msg = lock_user(VERIFY_WRITE, msg, len, 0); +- if (!host_msg) +- return -TARGET_EFAULT; +- if (target_addr) { +- if (get_user_u32(addrlen, target_addrlen)) { +- ret = -TARGET_EFAULT; +- goto fail; +- } +- if ((int)addrlen < 0) { +- ret = -TARGET_EINVAL; +- goto fail; +- } +- addr = alloca(addrlen); +- ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen)); +- } else { +- addr = NULL; /* To keep compiler quiet. */ +- ret = get_errno(qemu_recv(fd, host_msg, len, flags)); +- } +- if (!is_error(ret)) { +- if (target_addr) { +- host_to_target_sockaddr(target_addr, addr, addrlen); +- if (put_user_u32(addrlen, target_addrlen)) { +- ret = -TARGET_EFAULT; +- goto fail; +- } +- } +- unlock_user(host_msg, msg, len); +- } else { +-fail: +- unlock_user(host_msg, msg, 0); +- } +- return ret; +-} +- +-#ifdef TARGET_NR_socketcall +-/* do_socketcall() Must return target values and target errnos. */ +-static abi_long do_socketcall(int num, abi_ulong vptr) +-{ +- static const unsigned ac[] = { /* number of arguments per call */ +- [SOCKOP_socket] = 3, /* domain, type, protocol */ +- [SOCKOP_bind] = 3, /* sockfd, addr, addrlen */ +- [SOCKOP_connect] = 3, /* sockfd, addr, addrlen */ +- [SOCKOP_listen] = 2, /* sockfd, backlog */ +- [SOCKOP_accept] = 3, /* sockfd, addr, addrlen */ +- [SOCKOP_accept4] = 4, /* sockfd, addr, addrlen, flags */ +- [SOCKOP_getsockname] = 3, /* sockfd, addr, addrlen */ +- [SOCKOP_getpeername] = 3, /* sockfd, addr, addrlen */ +- [SOCKOP_socketpair] = 4, /* domain, type, protocol, tab */ +- [SOCKOP_send] = 4, /* sockfd, msg, len, flags */ +- [SOCKOP_recv] = 4, /* sockfd, msg, len, flags */ +- [SOCKOP_sendto] = 6, /* sockfd, msg, len, flags, addr, addrlen */ +- [SOCKOP_recvfrom] = 6, /* sockfd, msg, len, flags, addr, addrlen */ +- [SOCKOP_shutdown] = 2, /* sockfd, how */ +- [SOCKOP_sendmsg] = 3, /* sockfd, msg, flags */ +- [SOCKOP_recvmsg] = 3, /* sockfd, msg, flags */ +- [SOCKOP_setsockopt] = 5, /* sockfd, level, optname, optval, optlen */ +- [SOCKOP_getsockopt] = 5, /* sockfd, level, optname, optval, optlen */ +- }; +- abi_long a[6]; /* max 6 args */ +- +- /* first, collect the arguments in a[] according to ac[] */ +- if (num >= 0 && num < ARRAY_SIZE(ac)) { +- unsigned i; +- assert(ARRAY_SIZE(a) >= ac[num]); /* ensure we have space for args */ +- for (i = 0; i < ac[num]; ++i) { +- if (get_user_ual(a[i], vptr + i * sizeof(abi_long)) != 0) { +- return -TARGET_EFAULT; +- } +- } +- } +- +- /* now when we have the args, actually handle the call */ +- switch (num) { +- case SOCKOP_socket: /* domain, type, protocol */ +- return do_socket(a[0], a[1], a[2]); +- case SOCKOP_bind: /* sockfd, addr, addrlen */ +- return do_bind(a[0], a[1], a[2]); +- case SOCKOP_connect: /* sockfd, addr, addrlen */ +- return do_connect(a[0], a[1], a[2]); +- case SOCKOP_listen: /* sockfd, backlog */ +- return get_errno(listen(a[0], a[1])); +- case SOCKOP_accept: /* sockfd, addr, addrlen */ +- return do_accept4(a[0], a[1], a[2], 0); +- case SOCKOP_accept4: /* sockfd, addr, addrlen, flags */ +- return do_accept4(a[0], a[1], a[2], a[3]); +- case SOCKOP_getsockname: /* sockfd, addr, addrlen */ +- return do_getsockname(a[0], a[1], a[2]); +- case SOCKOP_getpeername: /* sockfd, addr, addrlen */ +- return do_getpeername(a[0], a[1], a[2]); +- case SOCKOP_socketpair: /* domain, type, protocol, tab */ +- return do_socketpair(a[0], a[1], a[2], a[3]); +- case SOCKOP_send: /* sockfd, msg, len, flags */ +- return do_sendto(a[0], a[1], a[2], a[3], 0, 0); +- case SOCKOP_recv: /* sockfd, msg, len, flags */ +- return do_recvfrom(a[0], a[1], a[2], a[3], 0, 0); +- case SOCKOP_sendto: /* sockfd, msg, len, flags, addr, addrlen */ +- return do_sendto(a[0], a[1], a[2], a[3], a[4], a[5]); +- case SOCKOP_recvfrom: /* sockfd, msg, len, flags, addr, addrlen */ +- return do_recvfrom(a[0], a[1], a[2], a[3], a[4], a[5]); +- case SOCKOP_shutdown: /* sockfd, how */ +- return get_errno(shutdown(a[0], a[1])); +- case SOCKOP_sendmsg: /* sockfd, msg, flags */ +- return do_sendrecvmsg(a[0], a[1], a[2], 1); +- case SOCKOP_recvmsg: /* sockfd, msg, flags */ +- return do_sendrecvmsg(a[0], a[1], a[2], 0); +- case SOCKOP_setsockopt: /* sockfd, level, optname, optval, optlen */ +- return do_setsockopt(a[0], a[1], a[2], a[3], a[4]); +- case SOCKOP_getsockopt: /* sockfd, level, optname, optval, optlen */ +- return do_getsockopt(a[0], a[1], a[2], a[3], a[4]); +- default: +- gemu_log("Unsupported socketcall: %d\n", num); +- return -TARGET_ENOSYS; +- } +-} +-#endif +- +-#define N_SHM_REGIONS 32 +- +-static struct shm_region { +- abi_ulong start; +- abi_ulong size; +-} shm_regions[N_SHM_REGIONS]; +- +-struct target_semid_ds +-{ +- struct target_ipc_perm sem_perm; +- abi_ulong sem_otime; +-#if !defined(TARGET_PPC64) +- abi_ulong __unused1; +-#endif +- abi_ulong sem_ctime; +-#if !defined(TARGET_PPC64) +- abi_ulong __unused2; +-#endif +- abi_ulong sem_nsems; +- abi_ulong __unused3; +- abi_ulong __unused4; +-}; +- +-static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip, +- abi_ulong target_addr) +-{ +- struct target_ipc_perm *target_ip; +- struct target_semid_ds *target_sd; +- +- if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) +- return -TARGET_EFAULT; +- target_ip = &(target_sd->sem_perm); +- host_ip->__key = tswap32(target_ip->__key); +- host_ip->uid = tswap32(target_ip->uid); +- host_ip->gid = tswap32(target_ip->gid); +- host_ip->cuid = tswap32(target_ip->cuid); +- host_ip->cgid = tswap32(target_ip->cgid); +-#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC) +- host_ip->mode = tswap32(target_ip->mode); +-#else +- host_ip->mode = tswap16(target_ip->mode); +-#endif +-#if defined(TARGET_PPC) +- host_ip->__seq = tswap32(target_ip->__seq); +-#else +- host_ip->__seq = tswap16(target_ip->__seq); +-#endif +- unlock_user_struct(target_sd, target_addr, 0); +- return 0; +-} +- +-static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr, +- struct ipc_perm *host_ip) +-{ +- struct target_ipc_perm *target_ip; +- struct target_semid_ds *target_sd; +- +- if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) +- return -TARGET_EFAULT; +- target_ip = &(target_sd->sem_perm); +- target_ip->__key = tswap32(host_ip->__key); +- target_ip->uid = tswap32(host_ip->uid); +- target_ip->gid = tswap32(host_ip->gid); +- target_ip->cuid = tswap32(host_ip->cuid); +- target_ip->cgid = tswap32(host_ip->cgid); +-#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC) +- target_ip->mode = tswap32(host_ip->mode); +-#else +- target_ip->mode = tswap16(host_ip->mode); +-#endif +-#if defined(TARGET_PPC) +- target_ip->__seq = tswap32(host_ip->__seq); +-#else +- target_ip->__seq = tswap16(host_ip->__seq); +-#endif +- unlock_user_struct(target_sd, target_addr, 1); +- return 0; +-} +- +-static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd, +- abi_ulong target_addr) +-{ +- struct target_semid_ds *target_sd; +- +- if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) +- return -TARGET_EFAULT; +- if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr)) +- return -TARGET_EFAULT; +- host_sd->sem_nsems = tswapal(target_sd->sem_nsems); +- host_sd->sem_otime = tswapal(target_sd->sem_otime); +- host_sd->sem_ctime = tswapal(target_sd->sem_ctime); +- unlock_user_struct(target_sd, target_addr, 0); +- return 0; +-} +- +-static inline abi_long host_to_target_semid_ds(abi_ulong target_addr, +- struct semid_ds *host_sd) +-{ +- struct target_semid_ds *target_sd; +- +- if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) +- return -TARGET_EFAULT; +- if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm))) +- return -TARGET_EFAULT; +- target_sd->sem_nsems = tswapal(host_sd->sem_nsems); +- target_sd->sem_otime = tswapal(host_sd->sem_otime); +- target_sd->sem_ctime = tswapal(host_sd->sem_ctime); +- unlock_user_struct(target_sd, target_addr, 1); +- return 0; +-} +- +-struct target_seminfo { +- int semmap; +- int semmni; +- int semmns; +- int semmnu; +- int semmsl; +- int semopm; +- int semume; +- int semusz; +- int semvmx; +- int semaem; +-}; +- +-static inline abi_long host_to_target_seminfo(abi_ulong target_addr, +- struct seminfo *host_seminfo) +-{ +- struct target_seminfo *target_seminfo; +- if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0)) +- return -TARGET_EFAULT; +- __put_user(host_seminfo->semmap, &target_seminfo->semmap); +- __put_user(host_seminfo->semmni, &target_seminfo->semmni); +- __put_user(host_seminfo->semmns, &target_seminfo->semmns); +- __put_user(host_seminfo->semmnu, &target_seminfo->semmnu); +- __put_user(host_seminfo->semmsl, &target_seminfo->semmsl); +- __put_user(host_seminfo->semopm, &target_seminfo->semopm); +- __put_user(host_seminfo->semume, &target_seminfo->semume); +- __put_user(host_seminfo->semusz, &target_seminfo->semusz); +- __put_user(host_seminfo->semvmx, &target_seminfo->semvmx); +- __put_user(host_seminfo->semaem, &target_seminfo->semaem); +- unlock_user_struct(target_seminfo, target_addr, 1); +- return 0; +-} +- +-union semun { +- int val; +- struct semid_ds *buf; +- unsigned short *array; +- struct seminfo *__buf; +-}; +- +-union target_semun { +- int val; +- abi_ulong buf; +- abi_ulong array; +- abi_ulong __buf; +-}; +- +-static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array, +- abi_ulong target_addr) +-{ +- int nsems; +- unsigned short *array; +- union semun semun; +- struct semid_ds semid_ds; +- int i, ret; +- +- semun.buf = &semid_ds; +- +- ret = semctl(semid, 0, IPC_STAT, semun); +- if (ret == -1) +- return get_errno(ret); +- +- nsems = semid_ds.sem_nsems; +- +- *host_array = malloc(nsems*sizeof(unsigned short)); +- if (!*host_array) { +- return -TARGET_ENOMEM; +- } +- array = lock_user(VERIFY_READ, target_addr, +- nsems*sizeof(unsigned short), 1); +- if (!array) { +- free(*host_array); +- return -TARGET_EFAULT; +- } +- +- for(i=0; imsg_perm),target_addr)) +- return -TARGET_EFAULT; +- host_md->msg_stime = tswapal(target_md->msg_stime); +- host_md->msg_rtime = tswapal(target_md->msg_rtime); +- host_md->msg_ctime = tswapal(target_md->msg_ctime); +- host_md->__msg_cbytes = tswapal(target_md->__msg_cbytes); +- host_md->msg_qnum = tswapal(target_md->msg_qnum); +- host_md->msg_qbytes = tswapal(target_md->msg_qbytes); +- host_md->msg_lspid = tswapal(target_md->msg_lspid); +- host_md->msg_lrpid = tswapal(target_md->msg_lrpid); +- unlock_user_struct(target_md, target_addr, 0); +- return 0; +-} +- +-static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr, +- struct msqid_ds *host_md) +-{ +- struct target_msqid_ds *target_md; +- +- if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0)) +- return -TARGET_EFAULT; +- if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm))) +- return -TARGET_EFAULT; +- target_md->msg_stime = tswapal(host_md->msg_stime); +- target_md->msg_rtime = tswapal(host_md->msg_rtime); +- target_md->msg_ctime = tswapal(host_md->msg_ctime); +- target_md->__msg_cbytes = tswapal(host_md->__msg_cbytes); +- target_md->msg_qnum = tswapal(host_md->msg_qnum); +- target_md->msg_qbytes = tswapal(host_md->msg_qbytes); +- target_md->msg_lspid = tswapal(host_md->msg_lspid); +- target_md->msg_lrpid = tswapal(host_md->msg_lrpid); +- unlock_user_struct(target_md, target_addr, 1); +- return 0; +-} +- +-struct target_msginfo { +- int msgpool; +- int msgmap; +- int msgmax; +- int msgmnb; +- int msgmni; +- int msgssz; +- int msgtql; +- unsigned short int msgseg; +-}; +- +-static inline abi_long host_to_target_msginfo(abi_ulong target_addr, +- struct msginfo *host_msginfo) +-{ +- struct target_msginfo *target_msginfo; +- if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0)) +- return -TARGET_EFAULT; +- __put_user(host_msginfo->msgpool, &target_msginfo->msgpool); +- __put_user(host_msginfo->msgmap, &target_msginfo->msgmap); +- __put_user(host_msginfo->msgmax, &target_msginfo->msgmax); +- __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb); +- __put_user(host_msginfo->msgmni, &target_msginfo->msgmni); +- __put_user(host_msginfo->msgssz, &target_msginfo->msgssz); +- __put_user(host_msginfo->msgtql, &target_msginfo->msgtql); +- __put_user(host_msginfo->msgseg, &target_msginfo->msgseg); +- unlock_user_struct(target_msginfo, target_addr, 1); +- return 0; +-} +- +-static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr) +-{ +- struct msqid_ds dsarg; +- struct msginfo msginfo; +- abi_long ret = -TARGET_EINVAL; +- +- cmd &= 0xff; +- +- switch (cmd) { +- case IPC_STAT: +- case IPC_SET: +- case MSG_STAT: +- if (target_to_host_msqid_ds(&dsarg,ptr)) +- return -TARGET_EFAULT; +- ret = get_errno(msgctl(msgid, cmd, &dsarg)); +- if (host_to_target_msqid_ds(ptr,&dsarg)) +- return -TARGET_EFAULT; +- break; +- case IPC_RMID: +- ret = get_errno(msgctl(msgid, cmd, NULL)); +- break; +- case IPC_INFO: +- case MSG_INFO: +- ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo)); +- if (host_to_target_msginfo(ptr, &msginfo)) +- return -TARGET_EFAULT; +- break; +- } +- +- return ret; +-} +- +-struct target_msgbuf { +- abi_long mtype; +- char mtext[1]; +-}; +- +-static inline abi_long do_msgsnd(int msqid, abi_long msgp, +- ssize_t msgsz, int msgflg) +-{ +- struct target_msgbuf *target_mb; +- struct msgbuf *host_mb; +- abi_long ret = 0; +- +- if (msgsz < 0) { +- return -TARGET_EINVAL; +- } +- +- if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0)) +- return -TARGET_EFAULT; +- host_mb = malloc(msgsz+sizeof(long)); +- if (!host_mb) { +- unlock_user_struct(target_mb, msgp, 0); +- return -TARGET_ENOMEM; +- } +- host_mb->mtype = (abi_long) tswapal(target_mb->mtype); +- memcpy(host_mb->mtext, target_mb->mtext, msgsz); +- ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg)); +- free(host_mb); +- unlock_user_struct(target_mb, msgp, 0); +- +- return ret; +-} +- +-static inline abi_long do_msgrcv(int msqid, abi_long msgp, +- unsigned int msgsz, abi_long msgtyp, +- int msgflg) +-{ +- struct target_msgbuf *target_mb; +- char *target_mtext; +- struct msgbuf *host_mb; +- abi_long ret = 0; +- +- if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0)) +- return -TARGET_EFAULT; +- +- host_mb = g_malloc(msgsz+sizeof(long)); +- ret = get_errno(msgrcv(msqid, host_mb, msgsz, msgtyp, msgflg)); +- +- if (ret > 0) { +- abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong); +- target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0); +- if (!target_mtext) { +- ret = -TARGET_EFAULT; +- goto end; +- } +- memcpy(target_mb->mtext, host_mb->mtext, ret); +- unlock_user(target_mtext, target_mtext_addr, ret); +- } +- +- target_mb->mtype = tswapal(host_mb->mtype); +- +-end: +- if (target_mb) +- unlock_user_struct(target_mb, msgp, 1); +- g_free(host_mb); +- return ret; +-} +- +-static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd, +- abi_ulong target_addr) +-{ +- struct target_shmid_ds *target_sd; +- +- if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) +- return -TARGET_EFAULT; +- if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr)) +- return -TARGET_EFAULT; +- __get_user(host_sd->shm_segsz, &target_sd->shm_segsz); +- __get_user(host_sd->shm_atime, &target_sd->shm_atime); +- __get_user(host_sd->shm_dtime, &target_sd->shm_dtime); +- __get_user(host_sd->shm_ctime, &target_sd->shm_ctime); +- __get_user(host_sd->shm_cpid, &target_sd->shm_cpid); +- __get_user(host_sd->shm_lpid, &target_sd->shm_lpid); +- __get_user(host_sd->shm_nattch, &target_sd->shm_nattch); +- unlock_user_struct(target_sd, target_addr, 0); +- return 0; +-} +- +-static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr, +- struct shmid_ds *host_sd) +-{ +- struct target_shmid_ds *target_sd; +- +- if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) +- return -TARGET_EFAULT; +- if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm))) +- return -TARGET_EFAULT; +- __put_user(host_sd->shm_segsz, &target_sd->shm_segsz); +- __put_user(host_sd->shm_atime, &target_sd->shm_atime); +- __put_user(host_sd->shm_dtime, &target_sd->shm_dtime); +- __put_user(host_sd->shm_ctime, &target_sd->shm_ctime); +- __put_user(host_sd->shm_cpid, &target_sd->shm_cpid); +- __put_user(host_sd->shm_lpid, &target_sd->shm_lpid); +- __put_user(host_sd->shm_nattch, &target_sd->shm_nattch); +- unlock_user_struct(target_sd, target_addr, 1); +- return 0; +-} +- +-struct target_shminfo { +- abi_ulong shmmax; +- abi_ulong shmmin; +- abi_ulong shmmni; +- abi_ulong shmseg; +- abi_ulong shmall; +-}; +- +-static inline abi_long host_to_target_shminfo(abi_ulong target_addr, +- struct shminfo *host_shminfo) +-{ +- struct target_shminfo *target_shminfo; +- if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0)) +- return -TARGET_EFAULT; +- __put_user(host_shminfo->shmmax, &target_shminfo->shmmax); +- __put_user(host_shminfo->shmmin, &target_shminfo->shmmin); +- __put_user(host_shminfo->shmmni, &target_shminfo->shmmni); +- __put_user(host_shminfo->shmseg, &target_shminfo->shmseg); +- __put_user(host_shminfo->shmall, &target_shminfo->shmall); +- unlock_user_struct(target_shminfo, target_addr, 1); +- return 0; +-} +- +-struct target_shm_info { +- int used_ids; +- abi_ulong shm_tot; +- abi_ulong shm_rss; +- abi_ulong shm_swp; +- abi_ulong swap_attempts; +- abi_ulong swap_successes; +-}; +- +-static inline abi_long host_to_target_shm_info(abi_ulong target_addr, +- struct shm_info *host_shm_info) +-{ +- struct target_shm_info *target_shm_info; +- if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0)) +- return -TARGET_EFAULT; +- __put_user(host_shm_info->used_ids, &target_shm_info->used_ids); +- __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot); +- __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss); +- __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp); +- __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts); +- __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes); +- unlock_user_struct(target_shm_info, target_addr, 1); +- return 0; +-} +- +-static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf) +-{ +- struct shmid_ds dsarg; +- struct shminfo shminfo; +- struct shm_info shm_info; +- abi_long ret = -TARGET_EINVAL; +- +- cmd &= 0xff; +- +- switch(cmd) { +- case IPC_STAT: +- case IPC_SET: +- case SHM_STAT: +- if (target_to_host_shmid_ds(&dsarg, buf)) +- return -TARGET_EFAULT; +- ret = get_errno(shmctl(shmid, cmd, &dsarg)); +- if (host_to_target_shmid_ds(buf, &dsarg)) +- return -TARGET_EFAULT; +- break; +- case IPC_INFO: +- ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo)); +- if (host_to_target_shminfo(buf, &shminfo)) +- return -TARGET_EFAULT; +- break; +- case SHM_INFO: +- ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info)); +- if (host_to_target_shm_info(buf, &shm_info)) +- return -TARGET_EFAULT; +- break; +- case IPC_RMID: +- case SHM_LOCK: +- case SHM_UNLOCK: +- ret = get_errno(shmctl(shmid, cmd, NULL)); +- break; +- } +- +- return ret; +-} +- +-static inline abi_ulong do_shmat(int shmid, abi_ulong shmaddr, int shmflg) +-{ +- abi_long raddr; +- void *host_raddr; +- struct shmid_ds shm_info; +- int i,ret; +- +- /* find out the length of the shared memory segment */ +- ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info)); +- if (is_error(ret)) { +- /* can't get length, bail out */ +- return ret; +- } +- +- mmap_lock(); +- +- if (shmaddr) +- host_raddr = shmat(shmid, (void *)g2h(shmaddr), shmflg); +- else { +- abi_ulong mmap_start; +- +- mmap_start = mmap_find_vma(0, shm_info.shm_segsz); +- +- if (mmap_start == -1) { +- errno = ENOMEM; +- host_raddr = (void *)-1; +- } else +- host_raddr = shmat(shmid, g2h(mmap_start), shmflg | SHM_REMAP); +- } +- +- if (host_raddr == (void *)-1) { +- mmap_unlock(); +- return get_errno((long)host_raddr); +- } +- raddr=h2g((unsigned long)host_raddr); +- +- page_set_flags(raddr, raddr + shm_info.shm_segsz, +- PAGE_VALID | PAGE_READ | +- ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE)); +- +- for (i = 0; i < N_SHM_REGIONS; i++) { +- if (shm_regions[i].start == 0) { +- shm_regions[i].start = raddr; +- shm_regions[i].size = shm_info.shm_segsz; +- break; +- } +- } +- +- mmap_unlock(); +- return raddr; +- +-} +- +-static inline abi_long do_shmdt(abi_ulong shmaddr) +-{ +- int i; +- +- for (i = 0; i < N_SHM_REGIONS; ++i) { +- if (shm_regions[i].start == shmaddr) { +- shm_regions[i].start = 0; +- page_set_flags(shmaddr, shmaddr + shm_regions[i].size, 0); +- break; +- } +- } +- +- return get_errno(shmdt(g2h(shmaddr))); +-} +- +-#ifdef TARGET_NR_ipc +-/* ??? This only works with linear mappings. */ +-/* do_ipc() must return target values and target errnos. */ +-static abi_long do_ipc(unsigned int call, abi_long first, +- abi_long second, abi_long third, +- abi_long ptr, abi_long fifth) +-{ +- int version; +- abi_long ret = 0; +- +- version = call >> 16; +- call &= 0xffff; +- +- switch (call) { +- case IPCOP_semop: +- ret = do_semop(first, ptr, second); +- break; +- +- case IPCOP_semget: +- ret = get_errno(semget(first, second, third)); +- break; +- +- case IPCOP_semctl: { +- /* The semun argument to semctl is passed by value, so dereference the +- * ptr argument. */ +- abi_ulong atptr; +- get_user_ual(atptr, ptr); +- ret = do_semctl(first, second, third, +- (union target_semun) atptr); +- break; +- } +- +- case IPCOP_msgget: +- ret = get_errno(msgget(first, second)); +- break; +- +- case IPCOP_msgsnd: +- ret = do_msgsnd(first, ptr, second, third); +- break; +- +- case IPCOP_msgctl: +- ret = do_msgctl(first, second, ptr); +- break; +- +- case IPCOP_msgrcv: +- switch (version) { +- case 0: +- { +- struct target_ipc_kludge { +- abi_long msgp; +- abi_long msgtyp; +- } *tmp; +- +- if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) { +- ret = -TARGET_EFAULT; +- break; +- } +- +- ret = do_msgrcv(first, tswapal(tmp->msgp), second, tswapal(tmp->msgtyp), third); +- +- unlock_user_struct(tmp, ptr, 0); +- break; +- } +- default: +- ret = do_msgrcv(first, ptr, second, fifth, third); +- } +- break; +- +- case IPCOP_shmat: +- switch (version) { +- default: +- { +- abi_ulong raddr; +- raddr = do_shmat(first, ptr, second); +- if (is_error(raddr)) +- return get_errno(raddr); +- if (put_user_ual(raddr, third)) +- return -TARGET_EFAULT; +- break; +- } +- case 1: +- ret = -TARGET_EINVAL; +- break; +- } +- break; +- case IPCOP_shmdt: +- ret = do_shmdt(ptr); +- break; +- +- case IPCOP_shmget: +- /* IPC_* flag values are the same on all linux platforms */ +- ret = get_errno(shmget(first, second, third)); +- break; +- +- /* IPC_* and SHM_* command values are the same on all linux platforms */ +- case IPCOP_shmctl: +- ret = do_shmctl(first, second, ptr); +- break; +- default: +- gemu_log("Unsupported ipc call: %d (version %d)\n", call, version); +- ret = -TARGET_ENOSYS; +- break; +- } +- return ret; +-} +-#endif +- +-/* kernel structure types definitions */ +- +-#define STRUCT(name, ...) STRUCT_ ## name, +-#define STRUCT_SPECIAL(name) STRUCT_ ## name, +-enum { +-#include "syscall_types.h" +-}; +-#undef STRUCT +-#undef STRUCT_SPECIAL +- +-#define STRUCT(name, ...) static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL }; +-#define STRUCT_SPECIAL(name) +-#include "syscall_types.h" +-#undef STRUCT +-#undef STRUCT_SPECIAL +- +-typedef struct IOCTLEntry IOCTLEntry; +- +-typedef abi_long do_ioctl_fn(const IOCTLEntry *ie, uint8_t *buf_temp, +- int fd, abi_long cmd, abi_long arg); +- +-struct IOCTLEntry { +- int target_cmd; +- unsigned int host_cmd; +- const char *name; +- int access; +- do_ioctl_fn *do_ioctl; +- const argtype arg_type[5]; +-}; +- +-#define IOC_R 0x0001 +-#define IOC_W 0x0002 +-#define IOC_RW (IOC_R | IOC_W) +- +-#define MAX_STRUCT_SIZE 4096 +- +-#ifdef CONFIG_FIEMAP +-/* So fiemap access checks don't overflow on 32 bit systems. +- * This is very slightly smaller than the limit imposed by +- * the underlying kernel. +- */ +-#define FIEMAP_MAX_EXTENTS ((UINT_MAX - sizeof(struct fiemap)) \ +- / sizeof(struct fiemap_extent)) +- +-static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp, +- int fd, abi_long cmd, abi_long arg) +-{ +- /* The parameter for this ioctl is a struct fiemap followed +- * by an array of struct fiemap_extent whose size is set +- * in fiemap->fm_extent_count. The array is filled in by the +- * ioctl. +- */ +- int target_size_in, target_size_out; +- struct fiemap *fm; +- const argtype *arg_type = ie->arg_type; +- const argtype extent_arg_type[] = { MK_STRUCT(STRUCT_fiemap_extent) }; +- void *argptr, *p; +- abi_long ret; +- int i, extent_size = thunk_type_size(extent_arg_type, 0); +- uint32_t outbufsz; +- int free_fm = 0; +- +- assert(arg_type[0] == TYPE_PTR); +- assert(ie->access == IOC_RW); +- arg_type++; +- target_size_in = thunk_type_size(arg_type, 0); +- argptr = lock_user(VERIFY_READ, arg, target_size_in, 1); +- if (!argptr) { +- return -TARGET_EFAULT; +- } +- thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); +- unlock_user(argptr, arg, 0); +- fm = (struct fiemap *)buf_temp; +- if (fm->fm_extent_count > FIEMAP_MAX_EXTENTS) { +- return -TARGET_EINVAL; +- } +- +- outbufsz = sizeof (*fm) + +- (sizeof(struct fiemap_extent) * fm->fm_extent_count); +- +- if (outbufsz > MAX_STRUCT_SIZE) { +- /* We can't fit all the extents into the fixed size buffer. +- * Allocate one that is large enough and use it instead. +- */ +- fm = malloc(outbufsz); +- if (!fm) { +- return -TARGET_ENOMEM; +- } +- memcpy(fm, buf_temp, sizeof(struct fiemap)); +- free_fm = 1; +- } +- ret = get_errno(ioctl(fd, ie->host_cmd, fm)); +- if (!is_error(ret)) { +- target_size_out = target_size_in; +- /* An extent_count of 0 means we were only counting the extents +- * so there are no structs to copy +- */ +- if (fm->fm_extent_count != 0) { +- target_size_out += fm->fm_mapped_extents * extent_size; +- } +- argptr = lock_user(VERIFY_WRITE, arg, target_size_out, 0); +- if (!argptr) { +- ret = -TARGET_EFAULT; +- } else { +- /* Convert the struct fiemap */ +- thunk_convert(argptr, fm, arg_type, THUNK_TARGET); +- if (fm->fm_extent_count != 0) { +- p = argptr + target_size_in; +- /* ...and then all the struct fiemap_extents */ +- for (i = 0; i < fm->fm_mapped_extents; i++) { +- thunk_convert(p, &fm->fm_extents[i], extent_arg_type, +- THUNK_TARGET); +- p += extent_size; +- } +- } +- unlock_user(argptr, arg, target_size_out); +- } +- } +- if (free_fm) { +- free(fm); +- } +- return ret; +-} +-#endif +- +-static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp, +- int fd, abi_long cmd, abi_long arg) +-{ +- const argtype *arg_type = ie->arg_type; +- int target_size; +- void *argptr; +- int ret; +- struct ifconf *host_ifconf; +- uint32_t outbufsz; +- const argtype ifreq_arg_type[] = { MK_STRUCT(STRUCT_sockaddr_ifreq) }; +- int target_ifreq_size; +- int nb_ifreq; +- int free_buf = 0; +- int i; +- int target_ifc_len; +- abi_long target_ifc_buf; +- int host_ifc_len; +- char *host_ifc_buf; +- +- assert(arg_type[0] == TYPE_PTR); +- assert(ie->access == IOC_RW); +- +- arg_type++; +- target_size = thunk_type_size(arg_type, 0); +- +- argptr = lock_user(VERIFY_READ, arg, target_size, 1); +- if (!argptr) +- return -TARGET_EFAULT; +- thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); +- unlock_user(argptr, arg, 0); +- +- host_ifconf = (struct ifconf *)(unsigned long)buf_temp; +- target_ifc_len = host_ifconf->ifc_len; +- target_ifc_buf = (abi_long)(unsigned long)host_ifconf->ifc_buf; +- +- target_ifreq_size = thunk_type_size(ifreq_arg_type, 0); +- nb_ifreq = target_ifc_len / target_ifreq_size; +- host_ifc_len = nb_ifreq * sizeof(struct ifreq); +- +- outbufsz = sizeof(*host_ifconf) + host_ifc_len; +- if (outbufsz > MAX_STRUCT_SIZE) { +- /* We can't fit all the extents into the fixed size buffer. +- * Allocate one that is large enough and use it instead. +- */ +- host_ifconf = malloc(outbufsz); +- if (!host_ifconf) { +- return -TARGET_ENOMEM; +- } +- memcpy(host_ifconf, buf_temp, sizeof(*host_ifconf)); +- free_buf = 1; +- } +- host_ifc_buf = (char*)host_ifconf + sizeof(*host_ifconf); +- +- host_ifconf->ifc_len = host_ifc_len; +- host_ifconf->ifc_buf = host_ifc_buf; +- +- ret = get_errno(ioctl(fd, ie->host_cmd, host_ifconf)); +- if (!is_error(ret)) { +- /* convert host ifc_len to target ifc_len */ +- +- nb_ifreq = host_ifconf->ifc_len / sizeof(struct ifreq); +- target_ifc_len = nb_ifreq * target_ifreq_size; +- host_ifconf->ifc_len = target_ifc_len; +- +- /* restore target ifc_buf */ +- +- host_ifconf->ifc_buf = (char *)(unsigned long)target_ifc_buf; +- +- /* copy struct ifconf to target user */ +- +- argptr = lock_user(VERIFY_WRITE, arg, target_size, 0); +- if (!argptr) +- return -TARGET_EFAULT; +- thunk_convert(argptr, host_ifconf, arg_type, THUNK_TARGET); +- unlock_user(argptr, arg, target_size); +- +- /* copy ifreq[] to target user */ +- +- argptr = lock_user(VERIFY_WRITE, target_ifc_buf, target_ifc_len, 0); +- for (i = 0; i < nb_ifreq ; i++) { +- thunk_convert(argptr + i * target_ifreq_size, +- host_ifc_buf + i * sizeof(struct ifreq), +- ifreq_arg_type, THUNK_TARGET); +- } +- unlock_user(argptr, target_ifc_buf, target_ifc_len); +- } +- +- if (free_buf) { +- free(host_ifconf); +- } +- +- return ret; +-} +- +-static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd, +- abi_long cmd, abi_long arg) +-{ +- void *argptr; +- struct dm_ioctl *host_dm; +- abi_long guest_data; +- uint32_t guest_data_size; +- int target_size; +- const argtype *arg_type = ie->arg_type; +- abi_long ret; +- void *big_buf = NULL; +- char *host_data; +- +- arg_type++; +- target_size = thunk_type_size(arg_type, 0); +- argptr = lock_user(VERIFY_READ, arg, target_size, 1); +- if (!argptr) { +- ret = -TARGET_EFAULT; +- goto out; +- } +- thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); +- unlock_user(argptr, arg, 0); +- +- /* buf_temp is too small, so fetch things into a bigger buffer */ +- big_buf = g_malloc0(((struct dm_ioctl*)buf_temp)->data_size * 2); +- memcpy(big_buf, buf_temp, target_size); +- buf_temp = big_buf; +- host_dm = big_buf; +- +- guest_data = arg + host_dm->data_start; +- if ((guest_data - arg) < 0) { +- ret = -EINVAL; +- goto out; +- } +- guest_data_size = host_dm->data_size - host_dm->data_start; +- host_data = (char*)host_dm + host_dm->data_start; +- +- argptr = lock_user(VERIFY_READ, guest_data, guest_data_size, 1); +- switch (ie->host_cmd) { +- case DM_REMOVE_ALL: +- case DM_LIST_DEVICES: +- case DM_DEV_CREATE: +- case DM_DEV_REMOVE: +- case DM_DEV_SUSPEND: +- case DM_DEV_STATUS: +- case DM_DEV_WAIT: +- case DM_TABLE_STATUS: +- case DM_TABLE_CLEAR: +- case DM_TABLE_DEPS: +- case DM_LIST_VERSIONS: +- /* no input data */ +- break; +- case DM_DEV_RENAME: +- case DM_DEV_SET_GEOMETRY: +- /* data contains only strings */ +- memcpy(host_data, argptr, guest_data_size); +- break; +- case DM_TARGET_MSG: +- memcpy(host_data, argptr, guest_data_size); +- *(uint64_t*)host_data = tswap64(*(uint64_t*)argptr); +- break; +- case DM_TABLE_LOAD: +- { +- void *gspec = argptr; +- void *cur_data = host_data; +- const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) }; +- int spec_size = thunk_type_size(arg_type, 0); +- int i; +- +- for (i = 0; i < host_dm->target_count; i++) { +- struct dm_target_spec *spec = cur_data; +- uint32_t next; +- int slen; +- +- thunk_convert(spec, gspec, arg_type, THUNK_HOST); +- slen = strlen((char*)gspec + spec_size) + 1; +- next = spec->next; +- spec->next = sizeof(*spec) + slen; +- strcpy((char*)&spec[1], gspec + spec_size); +- gspec += next; +- cur_data += spec->next; +- } +- break; +- } +- default: +- ret = -TARGET_EINVAL; +- unlock_user(argptr, guest_data, 0); +- goto out; +- } +- unlock_user(argptr, guest_data, 0); +- +- ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); +- if (!is_error(ret)) { +- guest_data = arg + host_dm->data_start; +- guest_data_size = host_dm->data_size - host_dm->data_start; +- argptr = lock_user(VERIFY_WRITE, guest_data, guest_data_size, 0); +- switch (ie->host_cmd) { +- case DM_REMOVE_ALL: +- case DM_DEV_CREATE: +- case DM_DEV_REMOVE: +- case DM_DEV_RENAME: +- case DM_DEV_SUSPEND: +- case DM_DEV_STATUS: +- case DM_TABLE_LOAD: +- case DM_TABLE_CLEAR: +- case DM_TARGET_MSG: +- case DM_DEV_SET_GEOMETRY: +- /* no return data */ +- break; +- case DM_LIST_DEVICES: +- { +- struct dm_name_list *nl = (void*)host_dm + host_dm->data_start; +- uint32_t remaining_data = guest_data_size; +- void *cur_data = argptr; +- const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) }; +- int nl_size = 12; /* can't use thunk_size due to alignment */ +- +- while (1) { +- uint32_t next = nl->next; +- if (next) { +- nl->next = nl_size + (strlen(nl->name) + 1); +- } +- if (remaining_data < nl->next) { +- host_dm->flags |= DM_BUFFER_FULL_FLAG; +- break; +- } +- thunk_convert(cur_data, nl, arg_type, THUNK_TARGET); +- strcpy(cur_data + nl_size, nl->name); +- cur_data += nl->next; +- remaining_data -= nl->next; +- if (!next) { +- break; +- } +- nl = (void*)nl + next; +- } +- break; +- } +- case DM_DEV_WAIT: +- case DM_TABLE_STATUS: +- { +- struct dm_target_spec *spec = (void*)host_dm + host_dm->data_start; +- void *cur_data = argptr; +- const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) }; +- int spec_size = thunk_type_size(arg_type, 0); +- int i; +- +- for (i = 0; i < host_dm->target_count; i++) { +- uint32_t next = spec->next; +- int slen = strlen((char*)&spec[1]) + 1; +- spec->next = (cur_data - argptr) + spec_size + slen; +- if (guest_data_size < spec->next) { +- host_dm->flags |= DM_BUFFER_FULL_FLAG; +- break; +- } +- thunk_convert(cur_data, spec, arg_type, THUNK_TARGET); +- strcpy(cur_data + spec_size, (char*)&spec[1]); +- cur_data = argptr + spec->next; +- spec = (void*)host_dm + host_dm->data_start + next; +- } +- break; +- } +- case DM_TABLE_DEPS: +- { +- void *hdata = (void*)host_dm + host_dm->data_start; +- int count = *(uint32_t*)hdata; +- uint64_t *hdev = hdata + 8; +- uint64_t *gdev = argptr + 8; +- int i; +- +- *(uint32_t*)argptr = tswap32(count); +- for (i = 0; i < count; i++) { +- *gdev = tswap64(*hdev); +- gdev++; +- hdev++; +- } +- break; +- } +- case DM_LIST_VERSIONS: +- { +- struct dm_target_versions *vers = (void*)host_dm + host_dm->data_start; +- uint32_t remaining_data = guest_data_size; +- void *cur_data = argptr; +- const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_versions) }; +- int vers_size = thunk_type_size(arg_type, 0); +- +- while (1) { +- uint32_t next = vers->next; +- if (next) { +- vers->next = vers_size + (strlen(vers->name) + 1); +- } +- if (remaining_data < vers->next) { +- host_dm->flags |= DM_BUFFER_FULL_FLAG; +- break; +- } +- thunk_convert(cur_data, vers, arg_type, THUNK_TARGET); +- strcpy(cur_data + vers_size, vers->name); +- cur_data += vers->next; +- remaining_data -= vers->next; +- if (!next) { +- break; +- } +- vers = (void*)vers + next; +- } +- break; +- } +- default: +- unlock_user(argptr, guest_data, 0); +- ret = -TARGET_EINVAL; +- goto out; +- } +- unlock_user(argptr, guest_data, guest_data_size); +- +- argptr = lock_user(VERIFY_WRITE, arg, target_size, 0); +- if (!argptr) { +- ret = -TARGET_EFAULT; +- goto out; +- } +- thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET); +- unlock_user(argptr, arg, target_size); +- } +-out: +- g_free(big_buf); +- return ret; +-} +- +-static abi_long do_ioctl_blkpg(const IOCTLEntry *ie, uint8_t *buf_temp, int fd, +- abi_long cmd, abi_long arg) +-{ +- void *argptr; +- int target_size; +- const argtype *arg_type = ie->arg_type; +- const argtype part_arg_type[] = { MK_STRUCT(STRUCT_blkpg_partition) }; +- abi_long ret; +- +- struct blkpg_ioctl_arg *host_blkpg = (void*)buf_temp; +- struct blkpg_partition host_part; +- +- /* Read and convert blkpg */ +- arg_type++; +- target_size = thunk_type_size(arg_type, 0); +- argptr = lock_user(VERIFY_READ, arg, target_size, 1); +- if (!argptr) { +- ret = -TARGET_EFAULT; +- goto out; +- } +- thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); +- unlock_user(argptr, arg, 0); +- +- switch (host_blkpg->op) { +- case BLKPG_ADD_PARTITION: +- case BLKPG_DEL_PARTITION: +- /* payload is struct blkpg_partition */ +- break; +- default: +- /* Unknown opcode */ +- ret = -TARGET_EINVAL; +- goto out; +- } +- +- /* Read and convert blkpg->data */ +- arg = (abi_long)(uintptr_t)host_blkpg->data; +- target_size = thunk_type_size(part_arg_type, 0); +- argptr = lock_user(VERIFY_READ, arg, target_size, 1); +- if (!argptr) { +- ret = -TARGET_EFAULT; +- goto out; +- } +- thunk_convert(&host_part, argptr, part_arg_type, THUNK_HOST); +- unlock_user(argptr, arg, 0); +- +- /* Swizzle the data pointer to our local copy and call! */ +- host_blkpg->data = &host_part; +- ret = get_errno(ioctl(fd, ie->host_cmd, host_blkpg)); +- +-out: +- return ret; +-} +- +-static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp, +- int fd, abi_long cmd, abi_long arg) +-{ +- const argtype *arg_type = ie->arg_type; +- const StructEntry *se; +- const argtype *field_types; +- const int *dst_offsets, *src_offsets; +- int target_size; +- void *argptr; +- abi_ulong *target_rt_dev_ptr; +- unsigned long *host_rt_dev_ptr; +- abi_long ret; +- int i; +- +- assert(ie->access == IOC_W); +- assert(*arg_type == TYPE_PTR); +- arg_type++; +- assert(*arg_type == TYPE_STRUCT); +- target_size = thunk_type_size(arg_type, 0); +- argptr = lock_user(VERIFY_READ, arg, target_size, 1); +- if (!argptr) { +- return -TARGET_EFAULT; +- } +- arg_type++; +- assert(*arg_type == (int)STRUCT_rtentry); +- se = struct_entries + *arg_type++; +- assert(se->convert[0] == NULL); +- /* convert struct here to be able to catch rt_dev string */ +- field_types = se->field_types; +- dst_offsets = se->field_offsets[THUNK_HOST]; +- src_offsets = se->field_offsets[THUNK_TARGET]; +- for (i = 0; i < se->nb_fields; i++) { +- if (dst_offsets[i] == offsetof(struct rtentry, rt_dev)) { +- assert(*field_types == TYPE_PTRVOID); +- target_rt_dev_ptr = (abi_ulong *)(argptr + src_offsets[i]); +- host_rt_dev_ptr = (unsigned long *)(buf_temp + dst_offsets[i]); +- if (*target_rt_dev_ptr != 0) { +- *host_rt_dev_ptr = (unsigned long)lock_user_string( +- tswapal(*target_rt_dev_ptr)); +- if (!*host_rt_dev_ptr) { +- unlock_user(argptr, arg, 0); +- return -TARGET_EFAULT; +- } +- } else { +- *host_rt_dev_ptr = 0; +- } +- field_types++; +- continue; +- } +- field_types = thunk_convert(buf_temp + dst_offsets[i], +- argptr + src_offsets[i], +- field_types, THUNK_HOST); +- } +- unlock_user(argptr, arg, 0); +- +- ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); +- if (*host_rt_dev_ptr != 0) { +- unlock_user((void *)*host_rt_dev_ptr, +- *target_rt_dev_ptr, 0); +- } +- return ret; +-} +- +-static abi_long do_ioctl_kdsigaccept(const IOCTLEntry *ie, uint8_t *buf_temp, +- int fd, abi_long cmd, abi_long arg) +-{ +- int sig = target_to_host_signal(arg); +- return get_errno(ioctl(fd, ie->host_cmd, sig)); +-} +- +-static IOCTLEntry ioctl_entries[] = { +-#define IOCTL(cmd, access, ...) \ +- { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } }, +-#define IOCTL_SPECIAL(cmd, access, dofn, ...) \ +- { TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } }, +-#include "ioctls.h" +- { 0, 0, }, +-}; +- +-/* ??? Implement proper locking for ioctls. */ +-/* do_ioctl() Must return target values and target errnos. */ +-static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg) +-{ +- const IOCTLEntry *ie; +- const argtype *arg_type; +- abi_long ret; +- uint8_t buf_temp[MAX_STRUCT_SIZE]; +- int target_size; +- void *argptr; +- +- ie = ioctl_entries; +- for(;;) { +- if (ie->target_cmd == 0) { +- gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd); +- return -TARGET_ENOSYS; +- } +- if (ie->target_cmd == cmd) +- break; +- ie++; +- } +- arg_type = ie->arg_type; +-#if defined(DEBUG) +- gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name); +-#endif +- if (ie->do_ioctl) { +- return ie->do_ioctl(ie, buf_temp, fd, cmd, arg); +- } +- +- switch(arg_type[0]) { +- case TYPE_NULL: +- /* no argument */ +- ret = get_errno(ioctl(fd, ie->host_cmd)); +- break; +- case TYPE_PTRVOID: +- case TYPE_INT: +- /* int argment */ +- ret = get_errno(ioctl(fd, ie->host_cmd, arg)); +- break; +- case TYPE_PTR: +- arg_type++; +- target_size = thunk_type_size(arg_type, 0); +- switch(ie->access) { +- case IOC_R: +- ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); +- if (!is_error(ret)) { +- argptr = lock_user(VERIFY_WRITE, arg, target_size, 0); +- if (!argptr) +- return -TARGET_EFAULT; +- thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET); +- unlock_user(argptr, arg, target_size); +- } +- break; +- case IOC_W: +- argptr = lock_user(VERIFY_READ, arg, target_size, 1); +- if (!argptr) +- return -TARGET_EFAULT; +- thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); +- unlock_user(argptr, arg, 0); +- ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); +- break; +- default: +- case IOC_RW: +- argptr = lock_user(VERIFY_READ, arg, target_size, 1); +- if (!argptr) +- return -TARGET_EFAULT; +- thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); +- unlock_user(argptr, arg, 0); +- ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); +- if (!is_error(ret)) { +- argptr = lock_user(VERIFY_WRITE, arg, target_size, 0); +- if (!argptr) +- return -TARGET_EFAULT; +- thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET); +- unlock_user(argptr, arg, target_size); +- } +- break; +- } +- break; +- default: +- gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n", +- (long)cmd, arg_type[0]); +- ret = -TARGET_ENOSYS; +- break; +- } +- return ret; +-} +- +-static const bitmask_transtbl iflag_tbl[] = { +- { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK }, +- { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT }, +- { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR }, +- { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK }, +- { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK }, +- { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP }, +- { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR }, +- { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR }, +- { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL }, +- { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC }, +- { TARGET_IXON, TARGET_IXON, IXON, IXON }, +- { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY }, +- { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF }, +- { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL }, +- { 0, 0, 0, 0 } +-}; +- +-static const bitmask_transtbl oflag_tbl[] = { +- { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST }, +- { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC }, +- { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR }, +- { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL }, +- { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR }, +- { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET }, +- { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL }, +- { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL }, +- { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 }, +- { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 }, +- { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 }, +- { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 }, +- { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 }, +- { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 }, +- { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 }, +- { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 }, +- { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 }, +- { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 }, +- { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 }, +- { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 }, +- { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 }, +- { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 }, +- { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 }, +- { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 }, +- { 0, 0, 0, 0 } +-}; +- +-static const bitmask_transtbl cflag_tbl[] = { +- { TARGET_CBAUD, TARGET_B0, CBAUD, B0 }, +- { TARGET_CBAUD, TARGET_B50, CBAUD, B50 }, +- { TARGET_CBAUD, TARGET_B75, CBAUD, B75 }, +- { TARGET_CBAUD, TARGET_B110, CBAUD, B110 }, +- { TARGET_CBAUD, TARGET_B134, CBAUD, B134 }, +- { TARGET_CBAUD, TARGET_B150, CBAUD, B150 }, +- { TARGET_CBAUD, TARGET_B200, CBAUD, B200 }, +- { TARGET_CBAUD, TARGET_B300, CBAUD, B300 }, +- { TARGET_CBAUD, TARGET_B600, CBAUD, B600 }, +- { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 }, +- { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 }, +- { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 }, +- { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 }, +- { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 }, +- { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 }, +- { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 }, +- { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 }, +- { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 }, +- { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 }, +- { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 }, +- { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 }, +- { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 }, +- { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 }, +- { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 }, +- { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB }, +- { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD }, +- { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB }, +- { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD }, +- { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL }, +- { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL }, +- { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS }, +- { 0, 0, 0, 0 } +-}; +- +-static const bitmask_transtbl lflag_tbl[] = { +- { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG }, +- { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON }, +- { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE }, +- { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO }, +- { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE }, +- { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK }, +- { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL }, +- { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH }, +- { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP }, +- { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL }, +- { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT }, +- { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE }, +- { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO }, +- { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN }, +- { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN }, +- { 0, 0, 0, 0 } +-}; +- +-static void target_to_host_termios (void *dst, const void *src) +-{ +- struct host_termios *host = dst; +- const struct target_termios *target = src; +- +- host->c_iflag = +- target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl); +- host->c_oflag = +- target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl); +- host->c_cflag = +- target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl); +- host->c_lflag = +- target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl); +- host->c_line = target->c_line; +- +- memset(host->c_cc, 0, sizeof(host->c_cc)); +- host->c_cc[VINTR] = target->c_cc[TARGET_VINTR]; +- host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT]; +- host->c_cc[VERASE] = target->c_cc[TARGET_VERASE]; +- host->c_cc[VKILL] = target->c_cc[TARGET_VKILL]; +- host->c_cc[VEOF] = target->c_cc[TARGET_VEOF]; +- host->c_cc[VTIME] = target->c_cc[TARGET_VTIME]; +- host->c_cc[VMIN] = target->c_cc[TARGET_VMIN]; +- host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC]; +- host->c_cc[VSTART] = target->c_cc[TARGET_VSTART]; +- host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP]; +- host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP]; +- host->c_cc[VEOL] = target->c_cc[TARGET_VEOL]; +- host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT]; +- host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD]; +- host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE]; +- host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT]; +- host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2]; +-} +- +-static void host_to_target_termios (void *dst, const void *src) +-{ +- struct target_termios *target = dst; +- const struct host_termios *host = src; +- +- target->c_iflag = +- tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl)); +- target->c_oflag = +- tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl)); +- target->c_cflag = +- tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl)); +- target->c_lflag = +- tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl)); +- target->c_line = host->c_line; +- +- memset(target->c_cc, 0, sizeof(target->c_cc)); +- target->c_cc[TARGET_VINTR] = host->c_cc[VINTR]; +- target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT]; +- target->c_cc[TARGET_VERASE] = host->c_cc[VERASE]; +- target->c_cc[TARGET_VKILL] = host->c_cc[VKILL]; +- target->c_cc[TARGET_VEOF] = host->c_cc[VEOF]; +- target->c_cc[TARGET_VTIME] = host->c_cc[VTIME]; +- target->c_cc[TARGET_VMIN] = host->c_cc[VMIN]; +- target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC]; +- target->c_cc[TARGET_VSTART] = host->c_cc[VSTART]; +- target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP]; +- target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP]; +- target->c_cc[TARGET_VEOL] = host->c_cc[VEOL]; +- target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT]; +- target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD]; +- target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE]; +- target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT]; +- target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2]; +-} +- +-static const StructEntry struct_termios_def = { +- .convert = { host_to_target_termios, target_to_host_termios }, +- .size = { sizeof(struct target_termios), sizeof(struct host_termios) }, +- .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) }, +-}; +- +-static bitmask_transtbl mmap_flags_tbl[] = { +- { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED }, +- { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE }, +- { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED }, +- { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS }, +- { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN }, +- { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE }, +- { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE }, +- { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED }, +- { TARGET_MAP_NORESERVE, TARGET_MAP_NORESERVE, MAP_NORESERVE, +- MAP_NORESERVE }, +- { 0, 0, 0, 0 } +-}; +- +-#if defined(TARGET_I386) +- +-/* NOTE: there is really one LDT for all the threads */ +-static uint8_t *ldt_table; +- +-static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount) +-{ +- int size; +- void *p; +- +- if (!ldt_table) +- return 0; +- size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE; +- if (size > bytecount) +- size = bytecount; +- p = lock_user(VERIFY_WRITE, ptr, size, 0); +- if (!p) +- return -TARGET_EFAULT; +- /* ??? Should this by byteswapped? */ +- memcpy(p, ldt_table, size); +- unlock_user(p, ptr, size); +- return size; +-} +- +-/* XXX: add locking support */ +-static abi_long write_ldt(CPUX86State *env, +- abi_ulong ptr, unsigned long bytecount, int oldmode) +-{ +- struct target_modify_ldt_ldt_s ldt_info; +- struct target_modify_ldt_ldt_s *target_ldt_info; +- int seg_32bit, contents, read_exec_only, limit_in_pages; +- int seg_not_present, useable, lm; +- uint32_t *lp, entry_1, entry_2; +- +- if (bytecount != sizeof(ldt_info)) +- return -TARGET_EINVAL; +- if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1)) +- return -TARGET_EFAULT; +- ldt_info.entry_number = tswap32(target_ldt_info->entry_number); +- ldt_info.base_addr = tswapal(target_ldt_info->base_addr); +- ldt_info.limit = tswap32(target_ldt_info->limit); +- ldt_info.flags = tswap32(target_ldt_info->flags); +- unlock_user_struct(target_ldt_info, ptr, 0); +- +- if (ldt_info.entry_number >= TARGET_LDT_ENTRIES) +- return -TARGET_EINVAL; +- seg_32bit = ldt_info.flags & 1; +- contents = (ldt_info.flags >> 1) & 3; +- read_exec_only = (ldt_info.flags >> 3) & 1; +- limit_in_pages = (ldt_info.flags >> 4) & 1; +- seg_not_present = (ldt_info.flags >> 5) & 1; +- useable = (ldt_info.flags >> 6) & 1; +-#ifdef TARGET_ABI32 +- lm = 0; +-#else +- lm = (ldt_info.flags >> 7) & 1; +-#endif +- if (contents == 3) { +- if (oldmode) +- return -TARGET_EINVAL; +- if (seg_not_present == 0) +- return -TARGET_EINVAL; +- } +- /* allocate the LDT */ +- if (!ldt_table) { +- env->ldt.base = target_mmap(0, +- TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE, +- PROT_READ|PROT_WRITE, +- MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); +- if (env->ldt.base == -1) +- return -TARGET_ENOMEM; +- memset(g2h(env->ldt.base), 0, +- TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE); +- env->ldt.limit = 0xffff; +- ldt_table = g2h(env->ldt.base); +- } +- +- /* NOTE: same code as Linux kernel */ +- /* Allow LDTs to be cleared by the user. */ +- if (ldt_info.base_addr == 0 && ldt_info.limit == 0) { +- if (oldmode || +- (contents == 0 && +- read_exec_only == 1 && +- seg_32bit == 0 && +- limit_in_pages == 0 && +- seg_not_present == 1 && +- useable == 0 )) { +- entry_1 = 0; +- entry_2 = 0; +- goto install; +- } +- } +- +- entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) | +- (ldt_info.limit & 0x0ffff); +- entry_2 = (ldt_info.base_addr & 0xff000000) | +- ((ldt_info.base_addr & 0x00ff0000) >> 16) | +- (ldt_info.limit & 0xf0000) | +- ((read_exec_only ^ 1) << 9) | +- (contents << 10) | +- ((seg_not_present ^ 1) << 15) | +- (seg_32bit << 22) | +- (limit_in_pages << 23) | +- (lm << 21) | +- 0x7000; +- if (!oldmode) +- entry_2 |= (useable << 20); +- +- /* Install the new entry ... */ +-install: +- lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3)); +- lp[0] = tswap32(entry_1); +- lp[1] = tswap32(entry_2); +- return 0; +-} +- +-/* specific and weird i386 syscalls */ +-static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr, +- unsigned long bytecount) +-{ +- abi_long ret; +- +- switch (func) { +- case 0: +- ret = read_ldt(ptr, bytecount); +- break; +- case 1: +- ret = write_ldt(env, ptr, bytecount, 1); +- break; +- case 0x11: +- ret = write_ldt(env, ptr, bytecount, 0); +- break; +- default: +- ret = -TARGET_ENOSYS; +- break; +- } +- return ret; +-} +- +-#if defined(TARGET_I386) && defined(TARGET_ABI32) +-abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr) +-{ +- uint64_t *gdt_table = g2h(env->gdt.base); +- struct target_modify_ldt_ldt_s ldt_info; +- struct target_modify_ldt_ldt_s *target_ldt_info; +- int seg_32bit, contents, read_exec_only, limit_in_pages; +- int seg_not_present, useable, lm; +- uint32_t *lp, entry_1, entry_2; +- int i; +- +- lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1); +- if (!target_ldt_info) +- return -TARGET_EFAULT; +- ldt_info.entry_number = tswap32(target_ldt_info->entry_number); +- ldt_info.base_addr = tswapal(target_ldt_info->base_addr); +- ldt_info.limit = tswap32(target_ldt_info->limit); +- ldt_info.flags = tswap32(target_ldt_info->flags); +- if (ldt_info.entry_number == -1) { +- for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) { +- if (gdt_table[i] == 0) { +- ldt_info.entry_number = i; +- target_ldt_info->entry_number = tswap32(i); +- break; +- } +- } +- } +- unlock_user_struct(target_ldt_info, ptr, 1); +- +- if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN || +- ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX) +- return -TARGET_EINVAL; +- seg_32bit = ldt_info.flags & 1; +- contents = (ldt_info.flags >> 1) & 3; +- read_exec_only = (ldt_info.flags >> 3) & 1; +- limit_in_pages = (ldt_info.flags >> 4) & 1; +- seg_not_present = (ldt_info.flags >> 5) & 1; +- useable = (ldt_info.flags >> 6) & 1; +-#ifdef TARGET_ABI32 +- lm = 0; +-#else +- lm = (ldt_info.flags >> 7) & 1; +-#endif +- +- if (contents == 3) { +- if (seg_not_present == 0) +- return -TARGET_EINVAL; +- } +- +- /* NOTE: same code as Linux kernel */ +- /* Allow LDTs to be cleared by the user. */ +- if (ldt_info.base_addr == 0 && ldt_info.limit == 0) { +- if ((contents == 0 && +- read_exec_only == 1 && +- seg_32bit == 0 && +- limit_in_pages == 0 && +- seg_not_present == 1 && +- useable == 0 )) { +- entry_1 = 0; +- entry_2 = 0; +- goto install; +- } +- } +- +- entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) | +- (ldt_info.limit & 0x0ffff); +- entry_2 = (ldt_info.base_addr & 0xff000000) | +- ((ldt_info.base_addr & 0x00ff0000) >> 16) | +- (ldt_info.limit & 0xf0000) | +- ((read_exec_only ^ 1) << 9) | +- (contents << 10) | +- ((seg_not_present ^ 1) << 15) | +- (seg_32bit << 22) | +- (limit_in_pages << 23) | +- (useable << 20) | +- (lm << 21) | +- 0x7000; +- +- /* Install the new entry ... */ +-install: +- lp = (uint32_t *)(gdt_table + ldt_info.entry_number); +- lp[0] = tswap32(entry_1); +- lp[1] = tswap32(entry_2); +- return 0; +-} +- +-static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr) +-{ +- struct target_modify_ldt_ldt_s *target_ldt_info; +- uint64_t *gdt_table = g2h(env->gdt.base); +- uint32_t base_addr, limit, flags; +- int seg_32bit, contents, read_exec_only, limit_in_pages, idx; +- int seg_not_present, useable, lm; +- uint32_t *lp, entry_1, entry_2; +- +- lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1); +- if (!target_ldt_info) +- return -TARGET_EFAULT; +- idx = tswap32(target_ldt_info->entry_number); +- if (idx < TARGET_GDT_ENTRY_TLS_MIN || +- idx > TARGET_GDT_ENTRY_TLS_MAX) { +- unlock_user_struct(target_ldt_info, ptr, 1); +- return -TARGET_EINVAL; +- } +- lp = (uint32_t *)(gdt_table + idx); +- entry_1 = tswap32(lp[0]); +- entry_2 = tswap32(lp[1]); +- +- read_exec_only = ((entry_2 >> 9) & 1) ^ 1; +- contents = (entry_2 >> 10) & 3; +- seg_not_present = ((entry_2 >> 15) & 1) ^ 1; +- seg_32bit = (entry_2 >> 22) & 1; +- limit_in_pages = (entry_2 >> 23) & 1; +- useable = (entry_2 >> 20) & 1; +-#ifdef TARGET_ABI32 +- lm = 0; +-#else +- lm = (entry_2 >> 21) & 1; +-#endif +- flags = (seg_32bit << 0) | (contents << 1) | +- (read_exec_only << 3) | (limit_in_pages << 4) | +- (seg_not_present << 5) | (useable << 6) | (lm << 7); +- limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000); +- base_addr = (entry_1 >> 16) | +- (entry_2 & 0xff000000) | +- ((entry_2 & 0xff) << 16); +- target_ldt_info->base_addr = tswapal(base_addr); +- target_ldt_info->limit = tswap32(limit); +- target_ldt_info->flags = tswap32(flags); +- unlock_user_struct(target_ldt_info, ptr, 1); +- return 0; +-} +-#endif /* TARGET_I386 && TARGET_ABI32 */ +- +-#ifndef TARGET_ABI32 +-abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr) +-{ +- abi_long ret = 0; +- abi_ulong val; +- int idx; +- +- switch(code) { +- case TARGET_ARCH_SET_GS: +- case TARGET_ARCH_SET_FS: +- if (code == TARGET_ARCH_SET_GS) +- idx = R_GS; +- else +- idx = R_FS; +- cpu_x86_load_seg(env, idx, 0); +- env->segs[idx].base = addr; +- break; +- case TARGET_ARCH_GET_GS: +- case TARGET_ARCH_GET_FS: +- if (code == TARGET_ARCH_GET_GS) +- idx = R_GS; +- else +- idx = R_FS; +- val = env->segs[idx].base; +- if (put_user(val, addr, abi_ulong)) +- ret = -TARGET_EFAULT; +- break; +- default: +- ret = -TARGET_EINVAL; +- break; +- } +- return ret; +-} +-#endif +- +-#endif /* defined(TARGET_I386) */ +- +-#define NEW_STACK_SIZE 0x40000 +- +- +-static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER; +-typedef struct { +- CPUArchState *env; +- pthread_mutex_t mutex; +- pthread_cond_t cond; +- pthread_t thread; +- uint32_t tid; +- abi_ulong child_tidptr; +- abi_ulong parent_tidptr; +- sigset_t sigmask; +-} new_thread_info; +- +-static void *clone_func(void *arg) +-{ +- new_thread_info *info = arg; +- CPUArchState *env; +- CPUState *cpu; +- TaskState *ts; +- +- env = info->env; +- cpu = ENV_GET_CPU(env); +- thread_cpu = cpu; +- ts = (TaskState *)cpu->opaque; +- info->tid = gettid(); +- cpu->host_tid = info->tid; +- task_settid(ts); +- if (info->child_tidptr) +- put_user_u32(info->tid, info->child_tidptr); +- if (info->parent_tidptr) +- put_user_u32(info->tid, info->parent_tidptr); +- /* Enable signals. */ +- sigprocmask(SIG_SETMASK, &info->sigmask, NULL); +- /* Signal to the parent that we're ready. */ +- pthread_mutex_lock(&info->mutex); +- pthread_cond_broadcast(&info->cond); +- pthread_mutex_unlock(&info->mutex); +- /* Wait until the parent has finshed initializing the tls state. */ +- pthread_mutex_lock(&clone_lock); +- pthread_mutex_unlock(&clone_lock); +- cpu_loop(env); +- /* never exits */ +- return NULL; +-} +- +-/* do_fork() Must return host values and target errnos (unlike most +- do_*() functions). */ +-static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, +- abi_ulong parent_tidptr, target_ulong newtls, +- abi_ulong child_tidptr) +-{ +- CPUState *cpu = ENV_GET_CPU(env); +- int ret; +- TaskState *ts; +- CPUState *new_cpu; +- CPUArchState *new_env; +- unsigned int nptl_flags; +- sigset_t sigmask; +- +- /* Emulate vfork() with fork() */ +- if (flags & CLONE_VFORK) +- flags &= ~(CLONE_VFORK | CLONE_VM); +- +- if (flags & CLONE_VM) { +- TaskState *parent_ts = (TaskState *)cpu->opaque; +- new_thread_info info; +- pthread_attr_t attr; +- +- ts = g_malloc0(sizeof(TaskState)); +- init_task_state(ts); +- /* we create a new CPU instance. */ +- new_env = cpu_copy(env); +- /* Init regs that differ from the parent. */ +- cpu_clone_regs(new_env, newsp); +- new_cpu = ENV_GET_CPU(new_env); +- new_cpu->opaque = ts; +- ts->bprm = parent_ts->bprm; +- ts->info = parent_ts->info; +- nptl_flags = flags; +- flags &= ~CLONE_NPTL_FLAGS2; +- +- if (nptl_flags & CLONE_CHILD_CLEARTID) { +- ts->child_tidptr = child_tidptr; +- } +- +- if (nptl_flags & CLONE_SETTLS) +- cpu_set_tls (new_env, newtls); +- +- /* Grab a mutex so that thread setup appears atomic. */ +- pthread_mutex_lock(&clone_lock); +- +- memset(&info, 0, sizeof(info)); +- pthread_mutex_init(&info.mutex, NULL); +- pthread_mutex_lock(&info.mutex); +- pthread_cond_init(&info.cond, NULL); +- info.env = new_env; +- if (nptl_flags & CLONE_CHILD_SETTID) +- info.child_tidptr = child_tidptr; +- if (nptl_flags & CLONE_PARENT_SETTID) +- info.parent_tidptr = parent_tidptr; +- +- ret = pthread_attr_init(&attr); +- ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE); +- ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); +- /* It is not safe to deliver signals until the child has finished +- initializing, so temporarily block all signals. */ +- sigfillset(&sigmask); +- sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask); +- +- ret = pthread_create(&info.thread, &attr, clone_func, &info); +- /* TODO: Free new CPU state if thread creation failed. */ +- +- sigprocmask(SIG_SETMASK, &info.sigmask, NULL); +- pthread_attr_destroy(&attr); +- if (ret == 0) { +- /* Wait for the child to initialize. */ +- pthread_cond_wait(&info.cond, &info.mutex); +- ret = info.tid; +- if (flags & CLONE_PARENT_SETTID) +- put_user_u32(ret, parent_tidptr); +- } else { +- ret = -1; +- } +- pthread_mutex_unlock(&info.mutex); +- pthread_cond_destroy(&info.cond); +- pthread_mutex_destroy(&info.mutex); +- pthread_mutex_unlock(&clone_lock); +- } else { +- /* if no CLONE_VM, we consider it is a fork */ +- if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0) +- return -EINVAL; +- fork_start(); +- ret = fork(); +- if (ret == 0) { +- /* Child Process. */ +- rcu_after_fork(); +- cpu_clone_regs(env, newsp); +- fork_end(1); +- /* There is a race condition here. The parent process could +- theoretically read the TID in the child process before the child +- tid is set. This would require using either ptrace +- (not implemented) or having *_tidptr to point at a shared memory +- mapping. We can't repeat the spinlock hack used above because +- the child process gets its own copy of the lock. */ +- if (flags & CLONE_CHILD_SETTID) +- put_user_u32(gettid(), child_tidptr); +- if (flags & CLONE_PARENT_SETTID) +- put_user_u32(gettid(), parent_tidptr); +- ts = (TaskState *)cpu->opaque; +- if (flags & CLONE_SETTLS) +- cpu_set_tls (env, newtls); +- if (flags & CLONE_CHILD_CLEARTID) +- ts->child_tidptr = child_tidptr; +- } else { +- fork_end(0); +- } +- } +- return ret; +-} +- +-/* warning : doesn't handle linux specific flags... */ +-static int target_to_host_fcntl_cmd(int cmd) +-{ +- switch(cmd) { +- case TARGET_F_DUPFD: +- case TARGET_F_GETFD: +- case TARGET_F_SETFD: +- case TARGET_F_GETFL: +- case TARGET_F_SETFL: +- return cmd; +- case TARGET_F_GETLK: +- return F_GETLK; +- case TARGET_F_SETLK: +- return F_SETLK; +- case TARGET_F_SETLKW: +- return F_SETLKW; +- case TARGET_F_GETOWN: +- return F_GETOWN; +- case TARGET_F_SETOWN: +- return F_SETOWN; +- case TARGET_F_GETSIG: +- return F_GETSIG; +- case TARGET_F_SETSIG: +- return F_SETSIG; +-#if TARGET_ABI_BITS == 32 +- case TARGET_F_GETLK64: +- return F_GETLK64; +- case TARGET_F_SETLK64: +- return F_SETLK64; +- case TARGET_F_SETLKW64: +- return F_SETLKW64; +-#endif +- case TARGET_F_SETLEASE: +- return F_SETLEASE; +- case TARGET_F_GETLEASE: +- return F_GETLEASE; +-#ifdef F_DUPFD_CLOEXEC +- case TARGET_F_DUPFD_CLOEXEC: +- return F_DUPFD_CLOEXEC; +-#endif +- case TARGET_F_NOTIFY: +- return F_NOTIFY; +-#ifdef F_GETOWN_EX +- case TARGET_F_GETOWN_EX: +- return F_GETOWN_EX; +-#endif +-#ifdef F_SETOWN_EX +- case TARGET_F_SETOWN_EX: +- return F_SETOWN_EX; +-#endif +- default: +- return -TARGET_EINVAL; +- } +- return -TARGET_EINVAL; +-} +- +-#define TRANSTBL_CONVERT(a) { -1, TARGET_##a, -1, a } +-static const bitmask_transtbl flock_tbl[] = { +- TRANSTBL_CONVERT(F_RDLCK), +- TRANSTBL_CONVERT(F_WRLCK), +- TRANSTBL_CONVERT(F_UNLCK), +- TRANSTBL_CONVERT(F_EXLCK), +- TRANSTBL_CONVERT(F_SHLCK), +- { 0, 0, 0, 0 } +-}; +- +-static abi_long do_fcntl(int fd, int cmd, abi_ulong arg) +-{ +- struct flock fl; +- struct target_flock *target_fl; +- struct flock64 fl64; +- struct target_flock64 *target_fl64; +-#ifdef F_GETOWN_EX +- struct f_owner_ex fox; +- struct target_f_owner_ex *target_fox; +-#endif +- abi_long ret; +- int host_cmd = target_to_host_fcntl_cmd(cmd); +- +- if (host_cmd == -TARGET_EINVAL) +- return host_cmd; +- +- switch(cmd) { +- case TARGET_F_GETLK: +- if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1)) +- return -TARGET_EFAULT; +- fl.l_type = +- target_to_host_bitmask(tswap16(target_fl->l_type), flock_tbl); +- fl.l_whence = tswap16(target_fl->l_whence); +- fl.l_start = tswapal(target_fl->l_start); +- fl.l_len = tswapal(target_fl->l_len); +- fl.l_pid = tswap32(target_fl->l_pid); +- unlock_user_struct(target_fl, arg, 0); +- ret = get_errno(fcntl(fd, host_cmd, &fl)); +- if (ret == 0) { +- if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0)) +- return -TARGET_EFAULT; +- target_fl->l_type = +- host_to_target_bitmask(tswap16(fl.l_type), flock_tbl); +- target_fl->l_whence = tswap16(fl.l_whence); +- target_fl->l_start = tswapal(fl.l_start); +- target_fl->l_len = tswapal(fl.l_len); +- target_fl->l_pid = tswap32(fl.l_pid); +- unlock_user_struct(target_fl, arg, 1); +- } +- break; +- +- case TARGET_F_SETLK: +- case TARGET_F_SETLKW: +- if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1)) +- return -TARGET_EFAULT; +- fl.l_type = +- target_to_host_bitmask(tswap16(target_fl->l_type), flock_tbl); +- fl.l_whence = tswap16(target_fl->l_whence); +- fl.l_start = tswapal(target_fl->l_start); +- fl.l_len = tswapal(target_fl->l_len); +- fl.l_pid = tswap32(target_fl->l_pid); +- unlock_user_struct(target_fl, arg, 0); +- ret = get_errno(fcntl(fd, host_cmd, &fl)); +- break; +- +- case TARGET_F_GETLK64: +- if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1)) +- return -TARGET_EFAULT; +- fl64.l_type = +- target_to_host_bitmask(tswap16(target_fl64->l_type), flock_tbl) >> 1; +- fl64.l_whence = tswap16(target_fl64->l_whence); +- fl64.l_start = tswap64(target_fl64->l_start); +- fl64.l_len = tswap64(target_fl64->l_len); +- fl64.l_pid = tswap32(target_fl64->l_pid); +- unlock_user_struct(target_fl64, arg, 0); +- ret = get_errno(fcntl(fd, host_cmd, &fl64)); +- if (ret == 0) { +- if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0)) +- return -TARGET_EFAULT; +- target_fl64->l_type = +- host_to_target_bitmask(tswap16(fl64.l_type), flock_tbl) >> 1; +- target_fl64->l_whence = tswap16(fl64.l_whence); +- target_fl64->l_start = tswap64(fl64.l_start); +- target_fl64->l_len = tswap64(fl64.l_len); +- target_fl64->l_pid = tswap32(fl64.l_pid); +- unlock_user_struct(target_fl64, arg, 1); +- } +- break; +- case TARGET_F_SETLK64: +- case TARGET_F_SETLKW64: +- if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1)) +- return -TARGET_EFAULT; +- fl64.l_type = +- target_to_host_bitmask(tswap16(target_fl64->l_type), flock_tbl) >> 1; +- fl64.l_whence = tswap16(target_fl64->l_whence); +- fl64.l_start = tswap64(target_fl64->l_start); +- fl64.l_len = tswap64(target_fl64->l_len); +- fl64.l_pid = tswap32(target_fl64->l_pid); +- unlock_user_struct(target_fl64, arg, 0); +- ret = get_errno(fcntl(fd, host_cmd, &fl64)); +- break; +- +- case TARGET_F_GETFL: +- ret = get_errno(fcntl(fd, host_cmd, arg)); +- if (ret >= 0) { +- ret = host_to_target_bitmask(ret, fcntl_flags_tbl); +- } +- break; +- +- case TARGET_F_SETFL: +- ret = get_errno(fcntl(fd, host_cmd, target_to_host_bitmask(arg, fcntl_flags_tbl))); +- break; +- +-#ifdef F_GETOWN_EX +- case TARGET_F_GETOWN_EX: +- ret = get_errno(fcntl(fd, host_cmd, &fox)); +- if (ret >= 0) { +- if (!lock_user_struct(VERIFY_WRITE, target_fox, arg, 0)) +- return -TARGET_EFAULT; +- target_fox->type = tswap32(fox.type); +- target_fox->pid = tswap32(fox.pid); +- unlock_user_struct(target_fox, arg, 1); +- } +- break; +-#endif +- +-#ifdef F_SETOWN_EX +- case TARGET_F_SETOWN_EX: +- if (!lock_user_struct(VERIFY_READ, target_fox, arg, 1)) +- return -TARGET_EFAULT; +- fox.type = tswap32(target_fox->type); +- fox.pid = tswap32(target_fox->pid); +- unlock_user_struct(target_fox, arg, 0); +- ret = get_errno(fcntl(fd, host_cmd, &fox)); +- break; +-#endif +- +- case TARGET_F_SETOWN: +- case TARGET_F_GETOWN: +- case TARGET_F_SETSIG: +- case TARGET_F_GETSIG: +- case TARGET_F_SETLEASE: +- case TARGET_F_GETLEASE: +- ret = get_errno(fcntl(fd, host_cmd, arg)); +- break; +- +- default: +- ret = get_errno(fcntl(fd, cmd, arg)); +- break; +- } +- return ret; +-} +- +-#ifdef USE_UID16 +- +-static inline int high2lowuid(int uid) +-{ +- if (uid > 65535) +- return 65534; +- else +- return uid; +-} +- +-static inline int high2lowgid(int gid) +-{ +- if (gid > 65535) +- return 65534; +- else +- return gid; +-} +- +-static inline int low2highuid(int uid) +-{ +- if ((int16_t)uid == -1) +- return -1; +- else +- return uid; +-} +- +-static inline int low2highgid(int gid) +-{ +- if ((int16_t)gid == -1) +- return -1; +- else +- return gid; +-} +-static inline int tswapid(int id) +-{ +- return tswap16(id); +-} +- +-#define put_user_id(x, gaddr) put_user_u16(x, gaddr) +- +-#else /* !USE_UID16 */ +-static inline int high2lowuid(int uid) +-{ +- return uid; +-} +-static inline int high2lowgid(int gid) +-{ +- return gid; +-} +-static inline int low2highuid(int uid) +-{ +- return uid; +-} +-static inline int low2highgid(int gid) +-{ +- return gid; +-} +-static inline int tswapid(int id) +-{ +- return tswap32(id); +-} +- +-#define put_user_id(x, gaddr) put_user_u32(x, gaddr) +- +-#endif /* USE_UID16 */ +- +-void syscall_init(void) +-{ +- IOCTLEntry *ie; +- const argtype *arg_type; +- int size; +- int i; +- +-#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def); +-#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def); +-#include "syscall_types.h" +-#undef STRUCT +-#undef STRUCT_SPECIAL +- +- /* Build target_to_host_errno_table[] table from +- * host_to_target_errno_table[]. */ +- for (i = 0; i < ERRNO_TABLE_SIZE; i++) { +- target_to_host_errno_table[host_to_target_errno_table[i]] = i; +- } +- +- /* we patch the ioctl size if necessary. We rely on the fact that +- no ioctl has all the bits at '1' in the size field */ +- ie = ioctl_entries; +- while (ie->target_cmd != 0) { +- if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) == +- TARGET_IOC_SIZEMASK) { +- arg_type = ie->arg_type; +- if (arg_type[0] != TYPE_PTR) { +- fprintf(stderr, "cannot patch size for ioctl 0x%x\n", +- ie->target_cmd); +- exit(1); +- } +- arg_type++; +- size = thunk_type_size(arg_type, 0); +- ie->target_cmd = (ie->target_cmd & +- ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) | +- (size << TARGET_IOC_SIZESHIFT); +- } +- +- /* automatic consistency check if same arch */ +-#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \ +- (defined(__x86_64__) && defined(TARGET_X86_64)) +- if (unlikely(ie->target_cmd != ie->host_cmd)) { +- fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n", +- ie->name, ie->target_cmd, ie->host_cmd); +- } +-#endif +- ie++; +- } +-} +- +-#if TARGET_ABI_BITS == 32 +-static inline uint64_t target_offset64(uint32_t word0, uint32_t word1) +-{ +-#ifdef TARGET_WORDS_BIGENDIAN +- return ((uint64_t)word0 << 32) | word1; +-#else +- return ((uint64_t)word1 << 32) | word0; +-#endif +-} +-#else /* TARGET_ABI_BITS == 32 */ +-static inline uint64_t target_offset64(uint64_t word0, uint64_t word1) +-{ +- return word0; +-} +-#endif /* TARGET_ABI_BITS != 32 */ +- +-#ifdef TARGET_NR_truncate64 +-static inline abi_long target_truncate64(void *cpu_env, const char *arg1, +- abi_long arg2, +- abi_long arg3, +- abi_long arg4) +-{ +- if (regpairs_aligned(cpu_env)) { +- arg2 = arg3; +- arg3 = arg4; +- } +- return get_errno(truncate64(arg1, target_offset64(arg2, arg3))); +-} +-#endif +- +-#ifdef TARGET_NR_ftruncate64 +-static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1, +- abi_long arg2, +- abi_long arg3, +- abi_long arg4) +-{ +- if (regpairs_aligned(cpu_env)) { +- arg2 = arg3; +- arg3 = arg4; +- } +- return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3))); +-} +-#endif +- +-static inline abi_long target_to_host_timespec(struct timespec *host_ts, +- abi_ulong target_addr) +-{ +- struct target_timespec *target_ts; +- +- if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1)) +- return -TARGET_EFAULT; +- host_ts->tv_sec = tswapal(target_ts->tv_sec); +- host_ts->tv_nsec = tswapal(target_ts->tv_nsec); +- unlock_user_struct(target_ts, target_addr, 0); +- return 0; +-} +- +-static inline abi_long host_to_target_timespec(abi_ulong target_addr, +- struct timespec *host_ts) +-{ +- struct target_timespec *target_ts; +- +- if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) +- return -TARGET_EFAULT; +- target_ts->tv_sec = tswapal(host_ts->tv_sec); +- target_ts->tv_nsec = tswapal(host_ts->tv_nsec); +- unlock_user_struct(target_ts, target_addr, 1); +- return 0; +-} +- +-static inline abi_long target_to_host_itimerspec(struct itimerspec *host_itspec, +- abi_ulong target_addr) +-{ +- struct target_itimerspec *target_itspec; +- +- if (!lock_user_struct(VERIFY_READ, target_itspec, target_addr, 1)) { +- return -TARGET_EFAULT; +- } +- +- host_itspec->it_interval.tv_sec = +- tswapal(target_itspec->it_interval.tv_sec); +- host_itspec->it_interval.tv_nsec = +- tswapal(target_itspec->it_interval.tv_nsec); +- host_itspec->it_value.tv_sec = tswapal(target_itspec->it_value.tv_sec); +- host_itspec->it_value.tv_nsec = tswapal(target_itspec->it_value.tv_nsec); +- +- unlock_user_struct(target_itspec, target_addr, 1); +- return 0; +-} +- +-static inline abi_long host_to_target_itimerspec(abi_ulong target_addr, +- struct itimerspec *host_its) +-{ +- struct target_itimerspec *target_itspec; +- +- if (!lock_user_struct(VERIFY_WRITE, target_itspec, target_addr, 0)) { +- return -TARGET_EFAULT; +- } +- +- target_itspec->it_interval.tv_sec = tswapal(host_its->it_interval.tv_sec); +- target_itspec->it_interval.tv_nsec = tswapal(host_its->it_interval.tv_nsec); +- +- target_itspec->it_value.tv_sec = tswapal(host_its->it_value.tv_sec); +- target_itspec->it_value.tv_nsec = tswapal(host_its->it_value.tv_nsec); +- +- unlock_user_struct(target_itspec, target_addr, 0); +- return 0; +-} +- +-static inline abi_long target_to_host_sigevent(struct sigevent *host_sevp, +- abi_ulong target_addr) +-{ +- struct target_sigevent *target_sevp; +- +- if (!lock_user_struct(VERIFY_READ, target_sevp, target_addr, 1)) { +- return -TARGET_EFAULT; +- } +- +- /* This union is awkward on 64 bit systems because it has a 32 bit +- * integer and a pointer in it; we follow the conversion approach +- * used for handling sigval types in signal.c so the guest should get +- * the correct value back even if we did a 64 bit byteswap and it's +- * using the 32 bit integer. +- */ +- host_sevp->sigev_value.sival_ptr = +- (void *)(uintptr_t)tswapal(target_sevp->sigev_value.sival_ptr); +- host_sevp->sigev_signo = +- target_to_host_signal(tswap32(target_sevp->sigev_signo)); +- host_sevp->sigev_notify = tswap32(target_sevp->sigev_notify); +- host_sevp->_sigev_un._tid = tswap32(target_sevp->_sigev_un._tid); +- +- unlock_user_struct(target_sevp, target_addr, 1); +- return 0; +-} +- +-#if defined(TARGET_NR_mlockall) +-static inline int target_to_host_mlockall_arg(int arg) +-{ +- int result = 0; +- +- if (arg & TARGET_MLOCKALL_MCL_CURRENT) { +- result |= MCL_CURRENT; +- } +- if (arg & TARGET_MLOCKALL_MCL_FUTURE) { +- result |= MCL_FUTURE; +- } +- return result; +-} +-#endif +- +-#if defined(TARGET_NR_stat64) || defined(TARGET_NR_newfstatat) +-static inline abi_long host_to_target_stat64(void *cpu_env, +- abi_ulong target_addr, +- struct stat *host_st) +-{ +-#if defined(TARGET_ARM) && defined(TARGET_ABI32) +- if (((CPUARMState *)cpu_env)->eabi) { +- struct target_eabi_stat64 *target_st; +- +- if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0)) +- return -TARGET_EFAULT; +- memset(target_st, 0, sizeof(struct target_eabi_stat64)); +- __put_user(host_st->st_dev, &target_st->st_dev); +- __put_user(host_st->st_ino, &target_st->st_ino); +-#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO +- __put_user(host_st->st_ino, &target_st->__st_ino); +-#endif +- __put_user(host_st->st_mode, &target_st->st_mode); +- __put_user(host_st->st_nlink, &target_st->st_nlink); +- __put_user(host_st->st_uid, &target_st->st_uid); +- __put_user(host_st->st_gid, &target_st->st_gid); +- __put_user(host_st->st_rdev, &target_st->st_rdev); +- __put_user(host_st->st_size, &target_st->st_size); +- __put_user(host_st->st_blksize, &target_st->st_blksize); +- __put_user(host_st->st_blocks, &target_st->st_blocks); +- __put_user(host_st->st_atime, &target_st->target_st_atime); +- __put_user(host_st->st_mtime, &target_st->target_st_mtime); +- __put_user(host_st->st_ctime, &target_st->target_st_ctime); +- unlock_user_struct(target_st, target_addr, 1); +- } else +-#endif +- { +-#if defined(TARGET_HAS_STRUCT_STAT64) +- struct target_stat64 *target_st; +-#else +- struct target_stat *target_st; +-#endif +- +- if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0)) +- return -TARGET_EFAULT; +- memset(target_st, 0, sizeof(*target_st)); +- __put_user(host_st->st_dev, &target_st->st_dev); +- __put_user(host_st->st_ino, &target_st->st_ino); +-#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO +- __put_user(host_st->st_ino, &target_st->__st_ino); +-#endif +- __put_user(host_st->st_mode, &target_st->st_mode); +- __put_user(host_st->st_nlink, &target_st->st_nlink); +- __put_user(host_st->st_uid, &target_st->st_uid); +- __put_user(host_st->st_gid, &target_st->st_gid); +- __put_user(host_st->st_rdev, &target_st->st_rdev); +- /* XXX: better use of kernel struct */ +- __put_user(host_st->st_size, &target_st->st_size); +- __put_user(host_st->st_blksize, &target_st->st_blksize); +- __put_user(host_st->st_blocks, &target_st->st_blocks); +- __put_user(host_st->st_atime, &target_st->target_st_atime); +- __put_user(host_st->st_mtime, &target_st->target_st_mtime); +- __put_user(host_st->st_ctime, &target_st->target_st_ctime); +- unlock_user_struct(target_st, target_addr, 1); +- } +- +- return 0; +-} +-#endif +- +-/* ??? Using host futex calls even when target atomic operations +- are not really atomic probably breaks things. However implementing +- futexes locally would make futexes shared between multiple processes +- tricky. However they're probably useless because guest atomic +- operations won't work either. */ +-static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout, +- target_ulong uaddr2, int val3) +-{ +- struct timespec ts, *pts; +- int base_op; +- +- /* ??? We assume FUTEX_* constants are the same on both host +- and target. */ +-#ifdef FUTEX_CMD_MASK +- base_op = op & FUTEX_CMD_MASK; +-#else +- base_op = op; +-#endif +- switch (base_op) { +- case FUTEX_WAIT: +- case FUTEX_WAIT_BITSET: +- if (timeout) { +- pts = &ts; +- target_to_host_timespec(pts, timeout); +- } else { +- pts = NULL; +- } +- return get_errno(sys_futex(g2h(uaddr), op, tswap32(val), +- pts, NULL, val3)); +- case FUTEX_WAKE: +- return get_errno(sys_futex(g2h(uaddr), op, val, NULL, NULL, 0)); +- case FUTEX_FD: +- return get_errno(sys_futex(g2h(uaddr), op, val, NULL, NULL, 0)); +- case FUTEX_REQUEUE: +- case FUTEX_CMP_REQUEUE: +- case FUTEX_WAKE_OP: +- /* For FUTEX_REQUEUE, FUTEX_CMP_REQUEUE, and FUTEX_WAKE_OP, the +- TIMEOUT parameter is interpreted as a uint32_t by the kernel. +- But the prototype takes a `struct timespec *'; insert casts +- to satisfy the compiler. We do not need to tswap TIMEOUT +- since it's not compared to guest memory. */ +- pts = (struct timespec *)(uintptr_t) timeout; +- return get_errno(sys_futex(g2h(uaddr), op, val, pts, +- g2h(uaddr2), +- (base_op == FUTEX_CMP_REQUEUE +- ? tswap32(val3) +- : val3))); +- default: +- return -TARGET_ENOSYS; +- } +-} +- +-/* Map host to target signal numbers for the wait family of syscalls. +- Assume all other status bits are the same. */ +-int host_to_target_waitstatus(int status) +-{ +- if (WIFSIGNALED(status)) { +- return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f); +- } +- if (WIFSTOPPED(status)) { +- return (host_to_target_signal(WSTOPSIG(status)) << 8) +- | (status & 0xff); +- } +- return status; +-} +- +-static int open_self_cmdline(void *cpu_env, int fd) +-{ +- int fd_orig = -1; +- bool word_skipped = false; +- +- fd_orig = open("/proc/self/cmdline", O_RDONLY); +- if (fd_orig < 0) { +- return fd_orig; +- } +- +- while (true) { +- ssize_t nb_read; +- char buf[128]; +- char *cp_buf = buf; +- +- nb_read = read(fd_orig, buf, sizeof(buf)); +- if (nb_read < 0) { +- fd_orig = close(fd_orig); +- return -1; +- } else if (nb_read == 0) { +- break; +- } +- +- if (!word_skipped) { +- /* Skip the first string, which is the path to qemu-*-static +- instead of the actual command. */ +- cp_buf = memchr(buf, 0, sizeof(buf)); +- if (cp_buf) { +- /* Null byte found, skip one string */ +- cp_buf++; +- nb_read -= cp_buf - buf; +- word_skipped = true; +- } +- } +- +- if (word_skipped) { +- if (write(fd, cp_buf, nb_read) != nb_read) { +- close(fd_orig); +- return -1; +- } +- } +- } +- +- return close(fd_orig); +-} +- +-static int open_self_maps(void *cpu_env, int fd) +-{ +- CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env); +- TaskState *ts = cpu->opaque; +- FILE *fp; +- char *line = NULL; +- size_t len = 0; +- ssize_t read; +- +- fp = fopen("/proc/self/maps", "r"); +- if (fp == NULL) { +- return -EACCES; +- } +- +- while ((read = getline(&line, &len, fp)) != -1) { +- int fields, dev_maj, dev_min, inode; +- uint64_t min, max, offset; +- char flag_r, flag_w, flag_x, flag_p; +- char path[512] = ""; +- fields = sscanf(line, "%"PRIx64"-%"PRIx64" %c%c%c%c %"PRIx64" %x:%x %d" +- " %512s", &min, &max, &flag_r, &flag_w, &flag_x, +- &flag_p, &offset, &dev_maj, &dev_min, &inode, path); +- +- if ((fields < 10) || (fields > 11)) { +- continue; +- } +- if (h2g_valid(min)) { +- int flags = page_get_flags(h2g(min)); +- max = h2g_valid(max - 1) ? max : (uintptr_t)g2h(GUEST_ADDR_MAX); +- if (page_check_range(h2g(min), max - min, flags) == -1) { +- continue; +- } +- if (h2g(min) == ts->info->stack_limit) { +- pstrcpy(path, sizeof(path), " [stack]"); +- } +- dprintf(fd, TARGET_ABI_FMT_lx "-" TARGET_ABI_FMT_lx +- " %c%c%c%c %08" PRIx64 " %02x:%02x %d %s%s\n", +- h2g(min), h2g(max - 1) + 1, flag_r, flag_w, +- flag_x, flag_p, offset, dev_maj, dev_min, inode, +- path[0] ? " " : "", path); +- } +- } +- +- free(line); +- fclose(fp); +- +- return 0; +-} +- +-static int open_self_stat(void *cpu_env, int fd) +-{ +- CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env); +- TaskState *ts = cpu->opaque; +- abi_ulong start_stack = ts->info->start_stack; +- int i; +- +- for (i = 0; i < 44; i++) { +- char buf[128]; +- int len; +- uint64_t val = 0; +- +- if (i == 0) { +- /* pid */ +- val = getpid(); +- snprintf(buf, sizeof(buf), "%"PRId64 " ", val); +- } else if (i == 1) { +- /* app name */ +- snprintf(buf, sizeof(buf), "(%s) ", ts->bprm->argv[0]); +- } else if (i == 27) { +- /* stack bottom */ +- val = start_stack; +- snprintf(buf, sizeof(buf), "%"PRId64 " ", val); +- } else { +- /* for the rest, there is MasterCard */ +- snprintf(buf, sizeof(buf), "0%c", i == 43 ? '\n' : ' '); +- } +- +- len = strlen(buf); +- if (write(fd, buf, len) != len) { +- return -1; +- } +- } +- +- return 0; +-} +- +-static int open_self_auxv(void *cpu_env, int fd) +-{ +- CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env); +- TaskState *ts = cpu->opaque; +- abi_ulong auxv = ts->info->saved_auxv; +- abi_ulong len = ts->info->auxv_len; +- char *ptr; +- +- /* +- * Auxiliary vector is stored in target process stack. +- * read in whole auxv vector and copy it to file +- */ +- ptr = lock_user(VERIFY_READ, auxv, len, 0); +- if (ptr != NULL) { +- while (len > 0) { +- ssize_t r; +- r = write(fd, ptr, len); +- if (r <= 0) { +- break; +- } +- len -= r; +- ptr += r; +- } +- lseek(fd, 0, SEEK_SET); +- unlock_user(ptr, auxv, len); +- } +- +- return 0; +-} +- +-static int is_proc_myself(const char *filename, const char *entry) +-{ +- if (!strncmp(filename, "/proc/", strlen("/proc/"))) { +- filename += strlen("/proc/"); +- if (!strncmp(filename, "self/", strlen("self/"))) { +- filename += strlen("self/"); +- } else if (*filename >= '1' && *filename <= '9') { +- char myself[80]; +- snprintf(myself, sizeof(myself), "%d/", getpid()); +- if (!strncmp(filename, myself, strlen(myself))) { +- filename += strlen(myself); +- } else { +- return 0; +- } +- } else { +- return 0; +- } +- if (!strcmp(filename, entry)) { +- return 1; +- } +- } +- return 0; +-} +- +-#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) +-static int is_proc(const char *filename, const char *entry) +-{ +- return strcmp(filename, entry) == 0; +-} +- +-static int open_net_route(void *cpu_env, int fd) +-{ +- FILE *fp; +- char *line = NULL; +- size_t len = 0; +- ssize_t read; +- +- fp = fopen("/proc/net/route", "r"); +- if (fp == NULL) { +- return -EACCES; +- } +- +- /* read header */ +- +- read = getline(&line, &len, fp); +- dprintf(fd, "%s", line); +- +- /* read routes */ +- +- while ((read = getline(&line, &len, fp)) != -1) { +- char iface[16]; +- uint32_t dest, gw, mask; +- unsigned int flags, refcnt, use, metric, mtu, window, irtt; +- sscanf(line, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n", +- iface, &dest, &gw, &flags, &refcnt, &use, &metric, +- &mask, &mtu, &window, &irtt); +- dprintf(fd, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n", +- iface, tswap32(dest), tswap32(gw), flags, refcnt, use, +- metric, tswap32(mask), mtu, window, irtt); +- } +- +- free(line); +- fclose(fp); +- +- return 0; +-} +-#endif +- +-static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags, mode_t mode) +-{ +- struct fake_open { +- const char *filename; +- int (*fill)(void *cpu_env, int fd); +- int (*cmp)(const char *s1, const char *s2); +- }; +- const struct fake_open *fake_open; +- static const struct fake_open fakes[] = { +- { "maps", open_self_maps, is_proc_myself }, +- { "stat", open_self_stat, is_proc_myself }, +- { "auxv", open_self_auxv, is_proc_myself }, +- { "cmdline", open_self_cmdline, is_proc_myself }, +-#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) +- { "/proc/net/route", open_net_route, is_proc }, +-#endif +- { NULL, NULL, NULL } +- }; +- +- if (is_proc_myself(pathname, "exe")) { +- int execfd = qemu_getauxval(AT_EXECFD); +- return execfd ? execfd : get_errno(sys_openat(dirfd, exec_path, flags, mode)); +- } +- +- for (fake_open = fakes; fake_open->filename; fake_open++) { +- if (fake_open->cmp(pathname, fake_open->filename)) { +- break; +- } +- } +- +- if (fake_open->filename) { +- const char *tmpdir; +- char filename[PATH_MAX]; +- int fd, r; +- +- /* create temporary file to map stat to */ +- tmpdir = getenv("TMPDIR"); +- if (!tmpdir) +- tmpdir = "/tmp"; +- snprintf(filename, sizeof(filename), "%s/qemu-open.XXXXXX", tmpdir); +- fd = mkstemp(filename); +- if (fd < 0) { +- return fd; +- } +- unlink(filename); +- +- if ((r = fake_open->fill(cpu_env, fd))) { +- close(fd); +- return r; +- } +- lseek(fd, 0, SEEK_SET); +- +- return fd; +- } +- +- return get_errno(sys_openat(dirfd, path(pathname), flags, mode)); +-} +- +-#define TIMER_MAGIC 0x0caf0000 +-#define TIMER_MAGIC_MASK 0xffff0000 +- +-/* Convert QEMU provided timer ID back to internal 16bit index format */ +-static target_timer_t get_timer_id(abi_long arg) +-{ +- target_timer_t timerid = arg; +- +- if ((timerid & TIMER_MAGIC_MASK) != TIMER_MAGIC) { +- return -TARGET_EINVAL; +- } +- +- timerid &= 0xffff; +- +- if (timerid >= ARRAY_SIZE(g_posix_timers)) { +- return -TARGET_EINVAL; +- } +- +- return timerid; +-} +- +-/* do_syscall() should always have a single exit point at the end so +- that actions, such as logging of syscall results, can be performed. +- All errnos that do_syscall() returns must be -TARGET_. */ +-abi_long do_syscall(void *cpu_env, int num, abi_long arg1, +- abi_long arg2, abi_long arg3, abi_long arg4, +- abi_long arg5, abi_long arg6, abi_long arg7, +- abi_long arg8) +-{ +- CPUState *cpu = ENV_GET_CPU(cpu_env); +- abi_long ret; +- struct stat st; +- struct statfs stfs; +- void *p; +- +-#ifdef DEBUG +- gemu_log("syscall %d", num); +-#endif +- if(do_strace) +- print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6); +- +- switch(num) { +- case TARGET_NR_exit: +- /* In old applications this may be used to implement _exit(2). +- However in threaded applictions it is used for thread termination, +- and _exit_group is used for application termination. +- Do thread termination if we have more then one thread. */ +- /* FIXME: This probably breaks if a signal arrives. We should probably +- be disabling signals. */ +- if (CPU_NEXT(first_cpu)) { +- TaskState *ts; +- +- cpu_list_lock(); +- /* Remove the CPU from the list. */ +- QTAILQ_REMOVE(&cpus, cpu, node); +- cpu_list_unlock(); +- ts = cpu->opaque; +- if (ts->child_tidptr) { +- put_user_u32(0, ts->child_tidptr); +- sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX, +- NULL, NULL, 0); +- } +- thread_cpu = NULL; +- object_unref(OBJECT(cpu)); +- g_free(ts); +- pthread_exit(NULL); +- } +-#ifdef TARGET_GPROF +- _mcleanup(); +-#endif +- gdb_exit(cpu_env, arg1); +- _exit(arg1); +- ret = 0; /* avoid warning */ +- break; +- case TARGET_NR_read: +- if (arg3 == 0) +- ret = 0; +- else { +- if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0))) +- goto efault; +- ret = get_errno(read(arg1, p, arg3)); +- unlock_user(p, arg2, ret); +- } +- break; +- case TARGET_NR_write: +- if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1))) +- goto efault; +- ret = get_errno(write(arg1, p, arg3)); +- unlock_user(p, arg2, 0); +- break; +- case TARGET_NR_open: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(do_openat(cpu_env, AT_FDCWD, p, +- target_to_host_bitmask(arg2, fcntl_flags_tbl), +- arg3)); +- unlock_user(p, arg1, 0); +- break; +- case TARGET_NR_openat: +- if (!(p = lock_user_string(arg2))) +- goto efault; +- ret = get_errno(do_openat(cpu_env, arg1, p, +- target_to_host_bitmask(arg3, fcntl_flags_tbl), +- arg4)); +- unlock_user(p, arg2, 0); +- break; +- case TARGET_NR_close: +- ret = get_errno(close(arg1)); +- break; +- case TARGET_NR_brk: +- ret = do_brk(arg1); +- break; +- case TARGET_NR_fork: +- ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, 0, 0, 0)); +- break; +-#ifdef TARGET_NR_waitpid +- case TARGET_NR_waitpid: +- { +- int status; +- ret = get_errno(waitpid(arg1, &status, arg3)); +- if (!is_error(ret) && arg2 && ret +- && put_user_s32(host_to_target_waitstatus(status), arg2)) +- goto efault; +- } +- break; +-#endif +-#ifdef TARGET_NR_waitid +- case TARGET_NR_waitid: +- { +- siginfo_t info; +- info.si_pid = 0; +- ret = get_errno(waitid(arg1, arg2, &info, arg4)); +- if (!is_error(ret) && arg3 && info.si_pid != 0) { +- if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0))) +- goto efault; +- host_to_target_siginfo(p, &info); +- unlock_user(p, arg3, sizeof(target_siginfo_t)); +- } +- } +- break; +-#endif +-#ifdef TARGET_NR_creat /* not on alpha */ +- case TARGET_NR_creat: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(creat(p, arg2)); +- unlock_user(p, arg1, 0); +- break; +-#endif +- case TARGET_NR_link: +- { +- void * p2; +- p = lock_user_string(arg1); +- p2 = lock_user_string(arg2); +- if (!p || !p2) +- ret = -TARGET_EFAULT; +- else +- ret = get_errno(link(p, p2)); +- unlock_user(p2, arg2, 0); +- unlock_user(p, arg1, 0); +- } +- break; +-#if defined(TARGET_NR_linkat) +- case TARGET_NR_linkat: +- { +- void * p2 = NULL; +- if (!arg2 || !arg4) +- goto efault; +- p = lock_user_string(arg2); +- p2 = lock_user_string(arg4); +- if (!p || !p2) +- ret = -TARGET_EFAULT; +- else +- ret = get_errno(linkat(arg1, p, arg3, p2, arg5)); +- unlock_user(p, arg2, 0); +- unlock_user(p2, arg4, 0); +- } +- break; +-#endif +- case TARGET_NR_unlink: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(unlink(p)); +- unlock_user(p, arg1, 0); +- break; +-#if defined(TARGET_NR_unlinkat) +- case TARGET_NR_unlinkat: +- if (!(p = lock_user_string(arg2))) +- goto efault; +- ret = get_errno(unlinkat(arg1, p, arg3)); +- unlock_user(p, arg2, 0); +- break; +-#endif +- case TARGET_NR_execve: +- { +- char **argp, **envp; +- int argc, envc; +- abi_ulong gp; +- abi_ulong guest_argp; +- abi_ulong guest_envp; +- abi_ulong addr; +- char **q; +- int total_size = 0; +- +- argc = 0; +- guest_argp = arg2; +- for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) { +- if (get_user_ual(addr, gp)) +- goto efault; +- if (!addr) +- break; +- argc++; +- } +- envc = 0; +- guest_envp = arg3; +- for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) { +- if (get_user_ual(addr, gp)) +- goto efault; +- if (!addr) +- break; +- envc++; +- } +- +- argp = alloca((argc + 1) * sizeof(void *)); +- envp = alloca((envc + 1) * sizeof(void *)); +- +- for (gp = guest_argp, q = argp; gp; +- gp += sizeof(abi_ulong), q++) { +- if (get_user_ual(addr, gp)) +- goto execve_efault; +- if (!addr) +- break; +- if (!(*q = lock_user_string(addr))) +- goto execve_efault; +- total_size += strlen(*q) + 1; +- } +- *q = NULL; +- +- for (gp = guest_envp, q = envp; gp; +- gp += sizeof(abi_ulong), q++) { +- if (get_user_ual(addr, gp)) +- goto execve_efault; +- if (!addr) +- break; +- if (!(*q = lock_user_string(addr))) +- goto execve_efault; +- total_size += strlen(*q) + 1; +- } +- *q = NULL; +- +- /* This case will not be caught by the host's execve() if its +- page size is bigger than the target's. */ +- if (total_size > MAX_ARG_PAGES * TARGET_PAGE_SIZE) { +- ret = -TARGET_E2BIG; +- goto execve_end; +- } +- if (!(p = lock_user_string(arg1))) +- goto execve_efault; +- ret = get_errno(execve(p, argp, envp)); +- unlock_user(p, arg1, 0); +- +- goto execve_end; +- +- execve_efault: +- ret = -TARGET_EFAULT; +- +- execve_end: +- for (gp = guest_argp, q = argp; *q; +- gp += sizeof(abi_ulong), q++) { +- if (get_user_ual(addr, gp) +- || !addr) +- break; +- unlock_user(*q, addr, 0); +- } +- for (gp = guest_envp, q = envp; *q; +- gp += sizeof(abi_ulong), q++) { +- if (get_user_ual(addr, gp) +- || !addr) +- break; +- unlock_user(*q, addr, 0); +- } +- } +- break; +- case TARGET_NR_chdir: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(chdir(p)); +- unlock_user(p, arg1, 0); +- break; +-#ifdef TARGET_NR_time +- case TARGET_NR_time: +- { +- time_t host_time; +- ret = get_errno(time(&host_time)); +- if (!is_error(ret) +- && arg1 +- && put_user_sal(host_time, arg1)) +- goto efault; +- } +- break; +-#endif +- case TARGET_NR_mknod: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(mknod(p, arg2, arg3)); +- unlock_user(p, arg1, 0); +- break; +-#if defined(TARGET_NR_mknodat) +- case TARGET_NR_mknodat: +- if (!(p = lock_user_string(arg2))) +- goto efault; +- ret = get_errno(mknodat(arg1, p, arg3, arg4)); +- unlock_user(p, arg2, 0); +- break; +-#endif +- case TARGET_NR_chmod: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(chmod(p, arg2)); +- unlock_user(p, arg1, 0); +- break; +-#ifdef TARGET_NR_break +- case TARGET_NR_break: +- goto unimplemented; +-#endif +-#ifdef TARGET_NR_oldstat +- case TARGET_NR_oldstat: +- goto unimplemented; +-#endif +- case TARGET_NR_lseek: +- ret = get_errno(lseek(arg1, arg2, arg3)); +- break; +-#if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA) +- /* Alpha specific */ +- case TARGET_NR_getxpid: +- ((CPUAlphaState *)cpu_env)->ir[IR_A4] = getppid(); +- ret = get_errno(getpid()); +- break; +-#endif +-#ifdef TARGET_NR_getpid +- case TARGET_NR_getpid: +- ret = get_errno(getpid()); +- break; +-#endif +- case TARGET_NR_mount: +- { +- /* need to look at the data field */ +- void *p2, *p3; +- +- if (arg1) { +- p = lock_user_string(arg1); +- if (!p) { +- goto efault; +- } +- } else { +- p = NULL; +- } +- +- p2 = lock_user_string(arg2); +- if (!p2) { +- if (arg1) { +- unlock_user(p, arg1, 0); +- } +- goto efault; +- } +- +- if (arg3) { +- p3 = lock_user_string(arg3); +- if (!p3) { +- if (arg1) { +- unlock_user(p, arg1, 0); +- } +- unlock_user(p2, arg2, 0); +- goto efault; +- } +- } else { +- p3 = NULL; +- } +- +- /* FIXME - arg5 should be locked, but it isn't clear how to +- * do that since it's not guaranteed to be a NULL-terminated +- * string. +- */ +- if (!arg5) { +- ret = mount(p, p2, p3, (unsigned long)arg4, NULL); +- } else { +- ret = mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)); +- } +- ret = get_errno(ret); +- +- if (arg1) { +- unlock_user(p, arg1, 0); +- } +- unlock_user(p2, arg2, 0); +- if (arg3) { +- unlock_user(p3, arg3, 0); +- } +- } +- break; +-#ifdef TARGET_NR_umount +- case TARGET_NR_umount: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(umount(p)); +- unlock_user(p, arg1, 0); +- break; +-#endif +-#ifdef TARGET_NR_stime /* not on alpha */ +- case TARGET_NR_stime: +- { +- time_t host_time; +- if (get_user_sal(host_time, arg1)) +- goto efault; +- ret = get_errno(stime(&host_time)); +- } +- break; +-#endif +- case TARGET_NR_ptrace: +- goto unimplemented; +-#ifdef TARGET_NR_alarm /* not on alpha */ +- case TARGET_NR_alarm: +- ret = alarm(arg1); +- break; +-#endif +-#ifdef TARGET_NR_oldfstat +- case TARGET_NR_oldfstat: +- goto unimplemented; +-#endif +-#ifdef TARGET_NR_pause /* not on alpha */ +- case TARGET_NR_pause: +- ret = get_errno(pause()); +- break; +-#endif +-#ifdef TARGET_NR_utime +- case TARGET_NR_utime: +- { +- struct utimbuf tbuf, *host_tbuf; +- struct target_utimbuf *target_tbuf; +- if (arg2) { +- if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1)) +- goto efault; +- tbuf.actime = tswapal(target_tbuf->actime); +- tbuf.modtime = tswapal(target_tbuf->modtime); +- unlock_user_struct(target_tbuf, arg2, 0); +- host_tbuf = &tbuf; +- } else { +- host_tbuf = NULL; +- } +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(utime(p, host_tbuf)); +- unlock_user(p, arg1, 0); +- } +- break; +-#endif +- case TARGET_NR_utimes: +- { +- struct timeval *tvp, tv[2]; +- if (arg2) { +- if (copy_from_user_timeval(&tv[0], arg2) +- || copy_from_user_timeval(&tv[1], +- arg2 + sizeof(struct target_timeval))) +- goto efault; +- tvp = tv; +- } else { +- tvp = NULL; +- } +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(utimes(p, tvp)); +- unlock_user(p, arg1, 0); +- } +- break; +-#if defined(TARGET_NR_futimesat) +- case TARGET_NR_futimesat: +- { +- struct timeval *tvp, tv[2]; +- if (arg3) { +- if (copy_from_user_timeval(&tv[0], arg3) +- || copy_from_user_timeval(&tv[1], +- arg3 + sizeof(struct target_timeval))) +- goto efault; +- tvp = tv; +- } else { +- tvp = NULL; +- } +- if (!(p = lock_user_string(arg2))) +- goto efault; +- ret = get_errno(futimesat(arg1, path(p), tvp)); +- unlock_user(p, arg2, 0); +- } +- break; +-#endif +-#ifdef TARGET_NR_stty +- case TARGET_NR_stty: +- goto unimplemented; +-#endif +-#ifdef TARGET_NR_gtty +- case TARGET_NR_gtty: +- goto unimplemented; +-#endif +- case TARGET_NR_access: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(access(path(p), arg2)); +- unlock_user(p, arg1, 0); +- break; +-#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat) +- case TARGET_NR_faccessat: +- if (!(p = lock_user_string(arg2))) +- goto efault; +- ret = get_errno(faccessat(arg1, p, arg3, 0)); +- unlock_user(p, arg2, 0); +- break; +-#endif +-#ifdef TARGET_NR_nice /* not on alpha */ +- case TARGET_NR_nice: +- ret = get_errno(nice(arg1)); +- break; +-#endif +-#ifdef TARGET_NR_ftime +- case TARGET_NR_ftime: +- goto unimplemented; +-#endif +- case TARGET_NR_sync: +- sync(); +- ret = 0; +- break; +- case TARGET_NR_kill: +- ret = get_errno(kill(arg1, target_to_host_signal(arg2))); +- break; +- case TARGET_NR_rename: +- { +- void *p2; +- p = lock_user_string(arg1); +- p2 = lock_user_string(arg2); +- if (!p || !p2) +- ret = -TARGET_EFAULT; +- else +- ret = get_errno(rename(p, p2)); +- unlock_user(p2, arg2, 0); +- unlock_user(p, arg1, 0); +- } +- break; +-#if defined(TARGET_NR_renameat) +- case TARGET_NR_renameat: +- { +- void *p2; +- p = lock_user_string(arg2); +- p2 = lock_user_string(arg4); +- if (!p || !p2) +- ret = -TARGET_EFAULT; +- else +- ret = get_errno(renameat(arg1, p, arg3, p2)); +- unlock_user(p2, arg4, 0); +- unlock_user(p, arg2, 0); +- } +- break; +-#endif +- case TARGET_NR_mkdir: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(mkdir(p, arg2)); +- unlock_user(p, arg1, 0); +- break; +-#if defined(TARGET_NR_mkdirat) +- case TARGET_NR_mkdirat: +- if (!(p = lock_user_string(arg2))) +- goto efault; +- ret = get_errno(mkdirat(arg1, p, arg3)); +- unlock_user(p, arg2, 0); +- break; +-#endif +- case TARGET_NR_rmdir: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(rmdir(p)); +- unlock_user(p, arg1, 0); +- break; +- case TARGET_NR_dup: +- ret = get_errno(dup(arg1)); +- break; +- case TARGET_NR_pipe: +- ret = do_pipe(cpu_env, arg1, 0, 0); +- break; +-#ifdef TARGET_NR_pipe2 +- case TARGET_NR_pipe2: +- ret = do_pipe(cpu_env, arg1, +- target_to_host_bitmask(arg2, fcntl_flags_tbl), 1); +- break; +-#endif +- case TARGET_NR_times: +- { +- struct target_tms *tmsp; +- struct tms tms; +- ret = get_errno(times(&tms)); +- if (arg1) { +- tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0); +- if (!tmsp) +- goto efault; +- tmsp->tms_utime = tswapal(host_to_target_clock_t(tms.tms_utime)); +- tmsp->tms_stime = tswapal(host_to_target_clock_t(tms.tms_stime)); +- tmsp->tms_cutime = tswapal(host_to_target_clock_t(tms.tms_cutime)); +- tmsp->tms_cstime = tswapal(host_to_target_clock_t(tms.tms_cstime)); +- } +- if (!is_error(ret)) +- ret = host_to_target_clock_t(ret); +- } +- break; +-#ifdef TARGET_NR_prof +- case TARGET_NR_prof: +- goto unimplemented; +-#endif +-#ifdef TARGET_NR_signal +- case TARGET_NR_signal: +- goto unimplemented; +-#endif +- case TARGET_NR_acct: +- if (arg1 == 0) { +- ret = get_errno(acct(NULL)); +- } else { +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(acct(path(p))); +- unlock_user(p, arg1, 0); +- } +- break; +-#ifdef TARGET_NR_umount2 +- case TARGET_NR_umount2: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(umount2(p, arg2)); +- unlock_user(p, arg1, 0); +- break; +-#endif +-#ifdef TARGET_NR_lock +- case TARGET_NR_lock: +- goto unimplemented; +-#endif +- case TARGET_NR_ioctl: +- ret = do_ioctl(arg1, arg2, arg3); +- break; +- case TARGET_NR_fcntl: +- ret = do_fcntl(arg1, arg2, arg3); +- break; +-#ifdef TARGET_NR_mpx +- case TARGET_NR_mpx: +- goto unimplemented; +-#endif +- case TARGET_NR_setpgid: +- ret = get_errno(setpgid(arg1, arg2)); +- break; +-#ifdef TARGET_NR_ulimit +- case TARGET_NR_ulimit: +- goto unimplemented; +-#endif +-#ifdef TARGET_NR_oldolduname +- case TARGET_NR_oldolduname: +- goto unimplemented; +-#endif +- case TARGET_NR_umask: +- ret = get_errno(umask(arg1)); +- break; +- case TARGET_NR_chroot: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(chroot(p)); +- unlock_user(p, arg1, 0); +- break; +- case TARGET_NR_ustat: +- goto unimplemented; +- case TARGET_NR_dup2: +- ret = get_errno(dup2(arg1, arg2)); +- break; +-#if defined(CONFIG_DUP3) && defined(TARGET_NR_dup3) +- case TARGET_NR_dup3: +- ret = get_errno(dup3(arg1, arg2, arg3)); +- break; +-#endif +-#ifdef TARGET_NR_getppid /* not on alpha */ +- case TARGET_NR_getppid: +- ret = get_errno(getppid()); +- break; +-#endif +- case TARGET_NR_getpgrp: +- ret = get_errno(getpgrp()); +- break; +- case TARGET_NR_setsid: +- ret = get_errno(setsid()); +- break; +-#ifdef TARGET_NR_sigaction +- case TARGET_NR_sigaction: +- { +-#if defined(TARGET_ALPHA) +- struct target_sigaction act, oact, *pact = 0; +- struct target_old_sigaction *old_act; +- if (arg2) { +- if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1)) +- goto efault; +- act._sa_handler = old_act->_sa_handler; +- target_siginitset(&act.sa_mask, old_act->sa_mask); +- act.sa_flags = old_act->sa_flags; +- act.sa_restorer = 0; +- unlock_user_struct(old_act, arg2, 0); +- pact = &act; +- } +- ret = get_errno(do_sigaction(arg1, pact, &oact)); +- if (!is_error(ret) && arg3) { +- if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0)) +- goto efault; +- old_act->_sa_handler = oact._sa_handler; +- old_act->sa_mask = oact.sa_mask.sig[0]; +- old_act->sa_flags = oact.sa_flags; +- unlock_user_struct(old_act, arg3, 1); +- } +-#elif defined(TARGET_MIPS) +- struct target_sigaction act, oact, *pact, *old_act; +- +- if (arg2) { +- if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1)) +- goto efault; +- act._sa_handler = old_act->_sa_handler; +- target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]); +- act.sa_flags = old_act->sa_flags; +- unlock_user_struct(old_act, arg2, 0); +- pact = &act; +- } else { +- pact = NULL; +- } +- +- ret = get_errno(do_sigaction(arg1, pact, &oact)); +- +- if (!is_error(ret) && arg3) { +- if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0)) +- goto efault; +- old_act->_sa_handler = oact._sa_handler; +- old_act->sa_flags = oact.sa_flags; +- old_act->sa_mask.sig[0] = oact.sa_mask.sig[0]; +- old_act->sa_mask.sig[1] = 0; +- old_act->sa_mask.sig[2] = 0; +- old_act->sa_mask.sig[3] = 0; +- unlock_user_struct(old_act, arg3, 1); +- } +-#else +- struct target_old_sigaction *old_act; +- struct target_sigaction act, oact, *pact; +- if (arg2) { +- if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1)) +- goto efault; +- act._sa_handler = old_act->_sa_handler; +- target_siginitset(&act.sa_mask, old_act->sa_mask); +- act.sa_flags = old_act->sa_flags; +- act.sa_restorer = old_act->sa_restorer; +- unlock_user_struct(old_act, arg2, 0); +- pact = &act; +- } else { +- pact = NULL; +- } +- ret = get_errno(do_sigaction(arg1, pact, &oact)); +- if (!is_error(ret) && arg3) { +- if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0)) +- goto efault; +- old_act->_sa_handler = oact._sa_handler; +- old_act->sa_mask = oact.sa_mask.sig[0]; +- old_act->sa_flags = oact.sa_flags; +- old_act->sa_restorer = oact.sa_restorer; +- unlock_user_struct(old_act, arg3, 1); +- } +-#endif +- } +- break; +-#endif +- case TARGET_NR_rt_sigaction: +- { +-#if defined(TARGET_ALPHA) +- struct target_sigaction act, oact, *pact = 0; +- struct target_rt_sigaction *rt_act; +- /* ??? arg4 == sizeof(sigset_t). */ +- if (arg2) { +- if (!lock_user_struct(VERIFY_READ, rt_act, arg2, 1)) +- goto efault; +- act._sa_handler = rt_act->_sa_handler; +- act.sa_mask = rt_act->sa_mask; +- act.sa_flags = rt_act->sa_flags; +- act.sa_restorer = arg5; +- unlock_user_struct(rt_act, arg2, 0); +- pact = &act; +- } +- ret = get_errno(do_sigaction(arg1, pact, &oact)); +- if (!is_error(ret) && arg3) { +- if (!lock_user_struct(VERIFY_WRITE, rt_act, arg3, 0)) +- goto efault; +- rt_act->_sa_handler = oact._sa_handler; +- rt_act->sa_mask = oact.sa_mask; +- rt_act->sa_flags = oact.sa_flags; +- unlock_user_struct(rt_act, arg3, 1); +- } +-#else +- struct target_sigaction *act; +- struct target_sigaction *oact; +- +- if (arg2) { +- if (!lock_user_struct(VERIFY_READ, act, arg2, 1)) +- goto efault; +- } else +- act = NULL; +- if (arg3) { +- if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) { +- ret = -TARGET_EFAULT; +- goto rt_sigaction_fail; +- } +- } else +- oact = NULL; +- ret = get_errno(do_sigaction(arg1, act, oact)); +- rt_sigaction_fail: +- if (act) +- unlock_user_struct(act, arg2, 0); +- if (oact) +- unlock_user_struct(oact, arg3, 1); +-#endif +- } +- break; +-#ifdef TARGET_NR_sgetmask /* not on alpha */ +- case TARGET_NR_sgetmask: +- { +- sigset_t cur_set; +- abi_ulong target_set; +- do_sigprocmask(0, NULL, &cur_set); +- host_to_target_old_sigset(&target_set, &cur_set); +- ret = target_set; +- } +- break; +-#endif +-#ifdef TARGET_NR_ssetmask /* not on alpha */ +- case TARGET_NR_ssetmask: +- { +- sigset_t set, oset, cur_set; +- abi_ulong target_set = arg1; +- do_sigprocmask(0, NULL, &cur_set); +- target_to_host_old_sigset(&set, &target_set); +- sigorset(&set, &set, &cur_set); +- do_sigprocmask(SIG_SETMASK, &set, &oset); +- host_to_target_old_sigset(&target_set, &oset); +- ret = target_set; +- } +- break; +-#endif +-#ifdef TARGET_NR_sigprocmask +- case TARGET_NR_sigprocmask: +- { +-#if defined(TARGET_ALPHA) +- sigset_t set, oldset; +- abi_ulong mask; +- int how; +- +- switch (arg1) { +- case TARGET_SIG_BLOCK: +- how = SIG_BLOCK; +- break; +- case TARGET_SIG_UNBLOCK: +- how = SIG_UNBLOCK; +- break; +- case TARGET_SIG_SETMASK: +- how = SIG_SETMASK; +- break; +- default: +- ret = -TARGET_EINVAL; +- goto fail; +- } +- mask = arg2; +- target_to_host_old_sigset(&set, &mask); +- +- ret = get_errno(do_sigprocmask(how, &set, &oldset)); +- if (!is_error(ret)) { +- host_to_target_old_sigset(&mask, &oldset); +- ret = mask; +- ((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0; /* force no error */ +- } +-#else +- sigset_t set, oldset, *set_ptr; +- int how; +- +- if (arg2) { +- switch (arg1) { +- case TARGET_SIG_BLOCK: +- how = SIG_BLOCK; +- break; +- case TARGET_SIG_UNBLOCK: +- how = SIG_UNBLOCK; +- break; +- case TARGET_SIG_SETMASK: +- how = SIG_SETMASK; +- break; +- default: +- ret = -TARGET_EINVAL; +- goto fail; +- } +- if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1))) +- goto efault; +- target_to_host_old_sigset(&set, p); +- unlock_user(p, arg2, 0); +- set_ptr = &set; +- } else { +- how = 0; +- set_ptr = NULL; +- } +- ret = get_errno(do_sigprocmask(how, set_ptr, &oldset)); +- if (!is_error(ret) && arg3) { +- if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0))) +- goto efault; +- host_to_target_old_sigset(p, &oldset); +- unlock_user(p, arg3, sizeof(target_sigset_t)); +- } +-#endif +- } +- break; +-#endif +- case TARGET_NR_rt_sigprocmask: +- { +- int how = arg1; +- sigset_t set, oldset, *set_ptr; +- +- if (arg2) { +- switch(how) { +- case TARGET_SIG_BLOCK: +- how = SIG_BLOCK; +- break; +- case TARGET_SIG_UNBLOCK: +- how = SIG_UNBLOCK; +- break; +- case TARGET_SIG_SETMASK: +- how = SIG_SETMASK; +- break; +- default: +- ret = -TARGET_EINVAL; +- goto fail; +- } +- if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1))) +- goto efault; +- target_to_host_sigset(&set, p); +- unlock_user(p, arg2, 0); +- set_ptr = &set; +- } else { +- how = 0; +- set_ptr = NULL; +- } +- ret = get_errno(do_sigprocmask(how, set_ptr, &oldset)); +- if (!is_error(ret) && arg3) { +- if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0))) +- goto efault; +- host_to_target_sigset(p, &oldset); +- unlock_user(p, arg3, sizeof(target_sigset_t)); +- } +- } +- break; +-#ifdef TARGET_NR_sigpending +- case TARGET_NR_sigpending: +- { +- sigset_t set; +- ret = get_errno(sigpending(&set)); +- if (!is_error(ret)) { +- if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0))) +- goto efault; +- host_to_target_old_sigset(p, &set); +- unlock_user(p, arg1, sizeof(target_sigset_t)); +- } +- } +- break; +-#endif +- case TARGET_NR_rt_sigpending: +- { +- sigset_t set; +- ret = get_errno(sigpending(&set)); +- if (!is_error(ret)) { +- if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0))) +- goto efault; +- host_to_target_sigset(p, &set); +- unlock_user(p, arg1, sizeof(target_sigset_t)); +- } +- } +- break; +-#ifdef TARGET_NR_sigsuspend +- case TARGET_NR_sigsuspend: +- { +- sigset_t set; +-#if defined(TARGET_ALPHA) +- abi_ulong mask = arg1; +- target_to_host_old_sigset(&set, &mask); +-#else +- if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1))) +- goto efault; +- target_to_host_old_sigset(&set, p); +- unlock_user(p, arg1, 0); +-#endif +- ret = get_errno(sigsuspend(&set)); +- } +- break; +-#endif +- case TARGET_NR_rt_sigsuspend: +- { +- sigset_t set; +- if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1))) +- goto efault; +- target_to_host_sigset(&set, p); +- unlock_user(p, arg1, 0); +- ret = get_errno(sigsuspend(&set)); +- } +- break; +- case TARGET_NR_rt_sigtimedwait: +- { +- sigset_t set; +- struct timespec uts, *puts; +- siginfo_t uinfo; +- +- if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1))) +- goto efault; +- target_to_host_sigset(&set, p); +- unlock_user(p, arg1, 0); +- if (arg3) { +- puts = &uts; +- target_to_host_timespec(puts, arg3); +- } else { +- puts = NULL; +- } +- ret = get_errno(sigtimedwait(&set, &uinfo, puts)); +- if (!is_error(ret)) { +- if (arg2) { +- p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), +- 0); +- if (!p) { +- goto efault; +- } +- host_to_target_siginfo(p, &uinfo); +- unlock_user(p, arg2, sizeof(target_siginfo_t)); +- } +- ret = host_to_target_signal(ret); +- } +- } +- break; +- case TARGET_NR_rt_sigqueueinfo: +- { +- siginfo_t uinfo; +- if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1))) +- goto efault; +- target_to_host_siginfo(&uinfo, p); +- unlock_user(p, arg1, 0); +- ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo)); +- } +- break; +-#ifdef TARGET_NR_sigreturn +- case TARGET_NR_sigreturn: +- /* NOTE: ret is eax, so not transcoding must be done */ +- ret = do_sigreturn(cpu_env); +- break; +-#endif +- case TARGET_NR_rt_sigreturn: +- /* NOTE: ret is eax, so not transcoding must be done */ +- ret = do_rt_sigreturn(cpu_env); +- break; +- case TARGET_NR_sethostname: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(sethostname(p, arg2)); +- unlock_user(p, arg1, 0); +- break; +- case TARGET_NR_setrlimit: +- { +- int resource = target_to_host_resource(arg1); +- struct target_rlimit *target_rlim; +- struct rlimit rlim; +- if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1)) +- goto efault; +- rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur); +- rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max); +- unlock_user_struct(target_rlim, arg2, 0); +- ret = get_errno(setrlimit(resource, &rlim)); +- } +- break; +- case TARGET_NR_getrlimit: +- { +- int resource = target_to_host_resource(arg1); +- struct target_rlimit *target_rlim; +- struct rlimit rlim; +- +- ret = get_errno(getrlimit(resource, &rlim)); +- if (!is_error(ret)) { +- if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0)) +- goto efault; +- target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur); +- target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max); +- unlock_user_struct(target_rlim, arg2, 1); +- } +- } +- break; +- case TARGET_NR_getrusage: +- { +- struct rusage rusage; +- ret = get_errno(getrusage(arg1, &rusage)); +- if (!is_error(ret)) { +- ret = host_to_target_rusage(arg2, &rusage); +- } +- } +- break; +- case TARGET_NR_gettimeofday: +- { +- struct timeval tv; +- ret = get_errno(gettimeofday(&tv, NULL)); +- if (!is_error(ret)) { +- if (copy_to_user_timeval(arg1, &tv)) +- goto efault; +- } +- } +- break; +- case TARGET_NR_settimeofday: +- { +- struct timeval tv, *ptv = NULL; +- struct timezone tz, *ptz = NULL; +- +- if (arg1) { +- if (copy_from_user_timeval(&tv, arg1)) { +- goto efault; +- } +- ptv = &tv; +- } +- +- if (arg2) { +- if (copy_from_user_timezone(&tz, arg2)) { +- goto efault; +- } +- ptz = &tz; +- } +- +- ret = get_errno(settimeofday(ptv, ptz)); +- } +- break; +-#if defined(TARGET_NR_select) +- case TARGET_NR_select: +-#if defined(TARGET_S390X) || defined(TARGET_ALPHA) +- ret = do_select(arg1, arg2, arg3, arg4, arg5); +-#else +- { +- struct target_sel_arg_struct *sel; +- abi_ulong inp, outp, exp, tvp; +- long nsel; +- +- if (!lock_user_struct(VERIFY_READ, sel, arg1, 1)) +- goto efault; +- nsel = tswapal(sel->n); +- inp = tswapal(sel->inp); +- outp = tswapal(sel->outp); +- exp = tswapal(sel->exp); +- tvp = tswapal(sel->tvp); +- unlock_user_struct(sel, arg1, 0); +- ret = do_select(nsel, inp, outp, exp, tvp); +- } +-#endif +- break; +-#endif +-#ifdef TARGET_NR_pselect6 +- case TARGET_NR_pselect6: +- { +- abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr; +- fd_set rfds, wfds, efds; +- fd_set *rfds_ptr, *wfds_ptr, *efds_ptr; +- struct timespec ts, *ts_ptr; +- +- /* +- * The 6th arg is actually two args smashed together, +- * so we cannot use the C library. +- */ +- sigset_t set; +- struct { +- sigset_t *set; +- size_t size; +- } sig, *sig_ptr; +- +- abi_ulong arg_sigset, arg_sigsize, *arg7; +- target_sigset_t *target_sigset; +- +- n = arg1; +- rfd_addr = arg2; +- wfd_addr = arg3; +- efd_addr = arg4; +- ts_addr = arg5; +- +- ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n); +- if (ret) { +- goto fail; +- } +- ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n); +- if (ret) { +- goto fail; +- } +- ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n); +- if (ret) { +- goto fail; +- } +- +- /* +- * This takes a timespec, and not a timeval, so we cannot +- * use the do_select() helper ... +- */ +- if (ts_addr) { +- if (target_to_host_timespec(&ts, ts_addr)) { +- goto efault; +- } +- ts_ptr = &ts; +- } else { +- ts_ptr = NULL; +- } +- +- /* Extract the two packed args for the sigset */ +- if (arg6) { +- sig_ptr = &sig; +- sig.size = _NSIG / 8; +- +- arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1); +- if (!arg7) { +- goto efault; +- } +- arg_sigset = tswapal(arg7[0]); +- arg_sigsize = tswapal(arg7[1]); +- unlock_user(arg7, arg6, 0); +- +- if (arg_sigset) { +- sig.set = &set; +- if (arg_sigsize != sizeof(*target_sigset)) { +- /* Like the kernel, we enforce correct size sigsets */ +- ret = -TARGET_EINVAL; +- goto fail; +- } +- target_sigset = lock_user(VERIFY_READ, arg_sigset, +- sizeof(*target_sigset), 1); +- if (!target_sigset) { +- goto efault; +- } +- target_to_host_sigset(&set, target_sigset); +- unlock_user(target_sigset, arg_sigset, 0); +- } else { +- sig.set = NULL; +- } +- } else { +- sig_ptr = NULL; +- } +- +- ret = get_errno(sys_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr, +- ts_ptr, sig_ptr)); +- +- if (!is_error(ret)) { +- if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n)) +- goto efault; +- if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n)) +- goto efault; +- if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n)) +- goto efault; +- +- if (ts_addr && host_to_target_timespec(ts_addr, &ts)) +- goto efault; +- } +- } +- break; +-#endif +- case TARGET_NR_symlink: +- { +- void *p2; +- p = lock_user_string(arg1); +- p2 = lock_user_string(arg2); +- if (!p || !p2) +- ret = -TARGET_EFAULT; +- else +- ret = get_errno(symlink(p, p2)); +- unlock_user(p2, arg2, 0); +- unlock_user(p, arg1, 0); +- } +- break; +-#if defined(TARGET_NR_symlinkat) +- case TARGET_NR_symlinkat: +- { +- void *p2; +- p = lock_user_string(arg1); +- p2 = lock_user_string(arg3); +- if (!p || !p2) +- ret = -TARGET_EFAULT; +- else +- ret = get_errno(symlinkat(p, arg2, p2)); +- unlock_user(p2, arg3, 0); +- unlock_user(p, arg1, 0); +- } +- break; +-#endif +-#ifdef TARGET_NR_oldlstat +- case TARGET_NR_oldlstat: +- goto unimplemented; +-#endif +- case TARGET_NR_readlink: +- { +- void *p2; +- p = lock_user_string(arg1); +- p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0); +- if (!p || !p2) { +- ret = -TARGET_EFAULT; +- } else if (!arg3) { +- /* Short circuit this for the magic exe check. */ +- ret = -TARGET_EINVAL; +- } else if (is_proc_myself((const char *)p, "exe")) { +- char real[PATH_MAX], *temp; +- temp = realpath(exec_path, real); +- /* Return value is # of bytes that we wrote to the buffer. */ +- if (temp == NULL) { +- ret = get_errno(-1); +- } else { +- /* Don't worry about sign mismatch as earlier mapping +- * logic would have thrown a bad address error. */ +- ret = MIN(strlen(real), arg3); +- /* We cannot NUL terminate the string. */ +- memcpy(p2, real, ret); +- } +- } else { +- ret = get_errno(readlink(path(p), p2, arg3)); +- } +- unlock_user(p2, arg2, ret); +- unlock_user(p, arg1, 0); +- } +- break; +-#if defined(TARGET_NR_readlinkat) +- case TARGET_NR_readlinkat: +- { +- void *p2; +- p = lock_user_string(arg2); +- p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0); +- if (!p || !p2) { +- ret = -TARGET_EFAULT; +- } else if (is_proc_myself((const char *)p, "exe")) { +- char real[PATH_MAX], *temp; +- temp = realpath(exec_path, real); +- ret = temp == NULL ? get_errno(-1) : strlen(real) ; +- snprintf((char *)p2, arg4, "%s", real); +- } else { +- ret = get_errno(readlinkat(arg1, path(p), p2, arg4)); +- } +- unlock_user(p2, arg3, ret); +- unlock_user(p, arg2, 0); +- } +- break; +-#endif +-#ifdef TARGET_NR_uselib +- case TARGET_NR_uselib: +- goto unimplemented; +-#endif +-#ifdef TARGET_NR_swapon +- case TARGET_NR_swapon: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(swapon(p, arg2)); +- unlock_user(p, arg1, 0); +- break; +-#endif +- case TARGET_NR_reboot: +- if (arg3 == LINUX_REBOOT_CMD_RESTART2) { +- /* arg4 must be ignored in all other cases */ +- p = lock_user_string(arg4); +- if (!p) { +- goto efault; +- } +- ret = get_errno(reboot(arg1, arg2, arg3, p)); +- unlock_user(p, arg4, 0); +- } else { +- ret = get_errno(reboot(arg1, arg2, arg3, NULL)); +- } +- break; +-#ifdef TARGET_NR_readdir +- case TARGET_NR_readdir: +- goto unimplemented; +-#endif +-#ifdef TARGET_NR_mmap +- case TARGET_NR_mmap: +-#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \ +- (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \ +- defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) \ +- || defined(TARGET_S390X) +- { +- abi_ulong *v; +- abi_ulong v1, v2, v3, v4, v5, v6; +- if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1))) +- goto efault; +- v1 = tswapal(v[0]); +- v2 = tswapal(v[1]); +- v3 = tswapal(v[2]); +- v4 = tswapal(v[3]); +- v5 = tswapal(v[4]); +- v6 = tswapal(v[5]); +- unlock_user(v, arg1, 0); +- ret = get_errno(target_mmap(v1, v2, v3, +- target_to_host_bitmask(v4, mmap_flags_tbl), +- v5, v6)); +- } +-#else +- ret = get_errno(target_mmap(arg1, arg2, arg3, +- target_to_host_bitmask(arg4, mmap_flags_tbl), +- arg5, +- arg6)); +-#endif +- break; +-#endif +-#ifdef TARGET_NR_mmap2 +- case TARGET_NR_mmap2: +-#ifndef MMAP_SHIFT +-#define MMAP_SHIFT 12 +-#endif +- ret = get_errno(target_mmap(arg1, arg2, arg3, +- target_to_host_bitmask(arg4, mmap_flags_tbl), +- arg5, +- arg6 << MMAP_SHIFT)); +- break; +-#endif +- case TARGET_NR_munmap: +- ret = get_errno(target_munmap(arg1, arg2)); +- break; +- case TARGET_NR_mprotect: +- { +- TaskState *ts = cpu->opaque; +- /* Special hack to detect libc making the stack executable. */ +- if ((arg3 & PROT_GROWSDOWN) +- && arg1 >= ts->info->stack_limit +- && arg1 <= ts->info->start_stack) { +- arg3 &= ~PROT_GROWSDOWN; +- arg2 = arg2 + arg1 - ts->info->stack_limit; +- arg1 = ts->info->stack_limit; +- } +- } +- ret = get_errno(target_mprotect(arg1, arg2, arg3)); +- break; +-#ifdef TARGET_NR_mremap +- case TARGET_NR_mremap: +- ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5)); +- break; +-#endif +- /* ??? msync/mlock/munlock are broken for softmmu. */ +-#ifdef TARGET_NR_msync +- case TARGET_NR_msync: +- ret = get_errno(msync(g2h(arg1), arg2, arg3)); +- break; +-#endif +-#ifdef TARGET_NR_mlock +- case TARGET_NR_mlock: +- ret = get_errno(mlock(g2h(arg1), arg2)); +- break; +-#endif +-#ifdef TARGET_NR_munlock +- case TARGET_NR_munlock: +- ret = get_errno(munlock(g2h(arg1), arg2)); +- break; +-#endif +-#ifdef TARGET_NR_mlockall +- case TARGET_NR_mlockall: +- ret = get_errno(mlockall(target_to_host_mlockall_arg(arg1))); +- break; +-#endif +-#ifdef TARGET_NR_munlockall +- case TARGET_NR_munlockall: +- ret = get_errno(munlockall()); +- break; +-#endif +- case TARGET_NR_truncate: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(truncate(p, arg2)); +- unlock_user(p, arg1, 0); +- break; +- case TARGET_NR_ftruncate: +- ret = get_errno(ftruncate(arg1, arg2)); +- break; +- case TARGET_NR_fchmod: +- ret = get_errno(fchmod(arg1, arg2)); +- break; +-#if defined(TARGET_NR_fchmodat) +- case TARGET_NR_fchmodat: +- if (!(p = lock_user_string(arg2))) +- goto efault; +- ret = get_errno(fchmodat(arg1, p, arg3, 0)); +- unlock_user(p, arg2, 0); +- break; +-#endif +- case TARGET_NR_getpriority: +- /* Note that negative values are valid for getpriority, so we must +- differentiate based on errno settings. */ +- errno = 0; +- ret = getpriority(arg1, arg2); +- if (ret == -1 && errno != 0) { +- ret = -host_to_target_errno(errno); +- break; +- } +-#ifdef TARGET_ALPHA +- /* Return value is the unbiased priority. Signal no error. */ +- ((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0; +-#else +- /* Return value is a biased priority to avoid negative numbers. */ +- ret = 20 - ret; +-#endif +- break; +- case TARGET_NR_setpriority: +- ret = get_errno(setpriority(arg1, arg2, arg3)); +- break; +-#ifdef TARGET_NR_profil +- case TARGET_NR_profil: +- goto unimplemented; +-#endif +- case TARGET_NR_statfs: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(statfs(path(p), &stfs)); +- unlock_user(p, arg1, 0); +- convert_statfs: +- if (!is_error(ret)) { +- struct target_statfs *target_stfs; +- +- if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0)) +- goto efault; +- __put_user(stfs.f_type, &target_stfs->f_type); +- __put_user(stfs.f_bsize, &target_stfs->f_bsize); +- __put_user(stfs.f_blocks, &target_stfs->f_blocks); +- __put_user(stfs.f_bfree, &target_stfs->f_bfree); +- __put_user(stfs.f_bavail, &target_stfs->f_bavail); +- __put_user(stfs.f_files, &target_stfs->f_files); +- __put_user(stfs.f_ffree, &target_stfs->f_ffree); +- __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]); +- __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]); +- __put_user(stfs.f_namelen, &target_stfs->f_namelen); +- __put_user(stfs.f_frsize, &target_stfs->f_frsize); +- memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare)); +- unlock_user_struct(target_stfs, arg2, 1); +- } +- break; +- case TARGET_NR_fstatfs: +- ret = get_errno(fstatfs(arg1, &stfs)); +- goto convert_statfs; +-#ifdef TARGET_NR_statfs64 +- case TARGET_NR_statfs64: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(statfs(path(p), &stfs)); +- unlock_user(p, arg1, 0); +- convert_statfs64: +- if (!is_error(ret)) { +- struct target_statfs64 *target_stfs; +- +- if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0)) +- goto efault; +- __put_user(stfs.f_type, &target_stfs->f_type); +- __put_user(stfs.f_bsize, &target_stfs->f_bsize); +- __put_user(stfs.f_blocks, &target_stfs->f_blocks); +- __put_user(stfs.f_bfree, &target_stfs->f_bfree); +- __put_user(stfs.f_bavail, &target_stfs->f_bavail); +- __put_user(stfs.f_files, &target_stfs->f_files); +- __put_user(stfs.f_ffree, &target_stfs->f_ffree); +- __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]); +- __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]); +- __put_user(stfs.f_namelen, &target_stfs->f_namelen); +- __put_user(stfs.f_frsize, &target_stfs->f_frsize); +- memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare)); +- unlock_user_struct(target_stfs, arg3, 1); +- } +- break; +- case TARGET_NR_fstatfs64: +- ret = get_errno(fstatfs(arg1, &stfs)); +- goto convert_statfs64; +-#endif +-#ifdef TARGET_NR_ioperm +- case TARGET_NR_ioperm: +- goto unimplemented; +-#endif +-#ifdef TARGET_NR_socketcall +- case TARGET_NR_socketcall: +- ret = do_socketcall(arg1, arg2); +- break; +-#endif +-#ifdef TARGET_NR_accept +- case TARGET_NR_accept: +- ret = do_accept4(arg1, arg2, arg3, 0); +- break; +-#endif +-#ifdef TARGET_NR_accept4 +- case TARGET_NR_accept4: +-#ifdef CONFIG_ACCEPT4 +- ret = do_accept4(arg1, arg2, arg3, arg4); +-#else +- goto unimplemented; +-#endif +- break; +-#endif +-#ifdef TARGET_NR_bind +- case TARGET_NR_bind: +- ret = do_bind(arg1, arg2, arg3); +- break; +-#endif +-#ifdef TARGET_NR_connect +- case TARGET_NR_connect: +- ret = do_connect(arg1, arg2, arg3); +- break; +-#endif +-#ifdef TARGET_NR_getpeername +- case TARGET_NR_getpeername: +- ret = do_getpeername(arg1, arg2, arg3); +- break; +-#endif +-#ifdef TARGET_NR_getsockname +- case TARGET_NR_getsockname: +- ret = do_getsockname(arg1, arg2, arg3); +- break; +-#endif +-#ifdef TARGET_NR_getsockopt +- case TARGET_NR_getsockopt: +- ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5); +- break; +-#endif +-#ifdef TARGET_NR_listen +- case TARGET_NR_listen: +- ret = get_errno(listen(arg1, arg2)); +- break; +-#endif +-#ifdef TARGET_NR_recv +- case TARGET_NR_recv: +- ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0); +- break; +-#endif +-#ifdef TARGET_NR_recvfrom +- case TARGET_NR_recvfrom: +- ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6); +- break; +-#endif +-#ifdef TARGET_NR_recvmsg +- case TARGET_NR_recvmsg: +- ret = do_sendrecvmsg(arg1, arg2, arg3, 0); +- break; +-#endif +-#ifdef TARGET_NR_send +- case TARGET_NR_send: +- ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0); +- break; +-#endif +-#ifdef TARGET_NR_sendmsg +- case TARGET_NR_sendmsg: +- ret = do_sendrecvmsg(arg1, arg2, arg3, 1); +- break; +-#endif +-#ifdef TARGET_NR_sendmmsg +- case TARGET_NR_sendmmsg: +- ret = do_sendrecvmmsg(arg1, arg2, arg3, arg4, 1); +- break; +- case TARGET_NR_recvmmsg: +- ret = do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0); +- break; +-#endif +-#ifdef TARGET_NR_sendto +- case TARGET_NR_sendto: +- ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6); +- break; +-#endif +-#ifdef TARGET_NR_shutdown +- case TARGET_NR_shutdown: +- ret = get_errno(shutdown(arg1, arg2)); +- break; +-#endif +-#ifdef TARGET_NR_socket +- case TARGET_NR_socket: +- ret = do_socket(arg1, arg2, arg3); +- break; +-#endif +-#ifdef TARGET_NR_socketpair +- case TARGET_NR_socketpair: +- ret = do_socketpair(arg1, arg2, arg3, arg4); +- break; +-#endif +-#ifdef TARGET_NR_setsockopt +- case TARGET_NR_setsockopt: +- ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5); +- break; +-#endif +- +- case TARGET_NR_syslog: +- if (!(p = lock_user_string(arg2))) +- goto efault; +- ret = get_errno(sys_syslog((int)arg1, p, (int)arg3)); +- unlock_user(p, arg2, 0); +- break; +- +- case TARGET_NR_setitimer: +- { +- struct itimerval value, ovalue, *pvalue; +- +- if (arg2) { +- pvalue = &value; +- if (copy_from_user_timeval(&pvalue->it_interval, arg2) +- || copy_from_user_timeval(&pvalue->it_value, +- arg2 + sizeof(struct target_timeval))) +- goto efault; +- } else { +- pvalue = NULL; +- } +- ret = get_errno(setitimer(arg1, pvalue, &ovalue)); +- if (!is_error(ret) && arg3) { +- if (copy_to_user_timeval(arg3, +- &ovalue.it_interval) +- || copy_to_user_timeval(arg3 + sizeof(struct target_timeval), +- &ovalue.it_value)) +- goto efault; +- } +- } +- break; +- case TARGET_NR_getitimer: +- { +- struct itimerval value; +- +- ret = get_errno(getitimer(arg1, &value)); +- if (!is_error(ret) && arg2) { +- if (copy_to_user_timeval(arg2, +- &value.it_interval) +- || copy_to_user_timeval(arg2 + sizeof(struct target_timeval), +- &value.it_value)) +- goto efault; +- } +- } +- break; +- case TARGET_NR_stat: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(stat(path(p), &st)); +- unlock_user(p, arg1, 0); +- goto do_stat; +- case TARGET_NR_lstat: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(lstat(path(p), &st)); +- unlock_user(p, arg1, 0); +- goto do_stat; +- case TARGET_NR_fstat: +- { +- ret = get_errno(fstat(arg1, &st)); +- do_stat: +- if (!is_error(ret)) { +- struct target_stat *target_st; +- +- if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0)) +- goto efault; +- memset(target_st, 0, sizeof(*target_st)); +- __put_user(st.st_dev, &target_st->st_dev); +- __put_user(st.st_ino, &target_st->st_ino); +- __put_user(st.st_mode, &target_st->st_mode); +- __put_user(st.st_uid, &target_st->st_uid); +- __put_user(st.st_gid, &target_st->st_gid); +- __put_user(st.st_nlink, &target_st->st_nlink); +- __put_user(st.st_rdev, &target_st->st_rdev); +- __put_user(st.st_size, &target_st->st_size); +- __put_user(st.st_blksize, &target_st->st_blksize); +- __put_user(st.st_blocks, &target_st->st_blocks); +- __put_user(st.st_atime, &target_st->target_st_atime); +- __put_user(st.st_mtime, &target_st->target_st_mtime); +- __put_user(st.st_ctime, &target_st->target_st_ctime); +- unlock_user_struct(target_st, arg2, 1); +- } +- } +- break; +-#ifdef TARGET_NR_olduname +- case TARGET_NR_olduname: +- goto unimplemented; +-#endif +-#ifdef TARGET_NR_iopl +- case TARGET_NR_iopl: +- goto unimplemented; +-#endif +- case TARGET_NR_vhangup: +- ret = get_errno(vhangup()); +- break; +-#ifdef TARGET_NR_idle +- case TARGET_NR_idle: +- goto unimplemented; +-#endif +-#ifdef TARGET_NR_syscall +- case TARGET_NR_syscall: +- ret = do_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4, arg5, +- arg6, arg7, arg8, 0); +- break; +-#endif +- case TARGET_NR_wait4: +- { +- int status; +- abi_long status_ptr = arg2; +- struct rusage rusage, *rusage_ptr; +- abi_ulong target_rusage = arg4; +- abi_long rusage_err; +- if (target_rusage) +- rusage_ptr = &rusage; +- else +- rusage_ptr = NULL; +- ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr)); +- if (!is_error(ret)) { +- if (status_ptr && ret) { +- status = host_to_target_waitstatus(status); +- if (put_user_s32(status, status_ptr)) +- goto efault; +- } +- if (target_rusage) { +- rusage_err = host_to_target_rusage(target_rusage, &rusage); +- if (rusage_err) { +- ret = rusage_err; +- } +- } +- } +- } +- break; +-#ifdef TARGET_NR_swapoff +- case TARGET_NR_swapoff: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(swapoff(p)); +- unlock_user(p, arg1, 0); +- break; +-#endif +- case TARGET_NR_sysinfo: +- { +- struct target_sysinfo *target_value; +- struct sysinfo value; +- ret = get_errno(sysinfo(&value)); +- if (!is_error(ret) && arg1) +- { +- if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0)) +- goto efault; +- __put_user(value.uptime, &target_value->uptime); +- __put_user(value.loads[0], &target_value->loads[0]); +- __put_user(value.loads[1], &target_value->loads[1]); +- __put_user(value.loads[2], &target_value->loads[2]); +- __put_user(value.totalram, &target_value->totalram); +- __put_user(value.freeram, &target_value->freeram); +- __put_user(value.sharedram, &target_value->sharedram); +- __put_user(value.bufferram, &target_value->bufferram); +- __put_user(value.totalswap, &target_value->totalswap); +- __put_user(value.freeswap, &target_value->freeswap); +- __put_user(value.procs, &target_value->procs); +- __put_user(value.totalhigh, &target_value->totalhigh); +- __put_user(value.freehigh, &target_value->freehigh); +- __put_user(value.mem_unit, &target_value->mem_unit); +- unlock_user_struct(target_value, arg1, 1); +- } +- } +- break; +-#ifdef TARGET_NR_ipc +- case TARGET_NR_ipc: +- ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6); +- break; +-#endif +-#ifdef TARGET_NR_semget +- case TARGET_NR_semget: +- ret = get_errno(semget(arg1, arg2, arg3)); +- break; +-#endif +-#ifdef TARGET_NR_semop +- case TARGET_NR_semop: +- ret = do_semop(arg1, arg2, arg3); +- break; +-#endif +-#ifdef TARGET_NR_semctl +- case TARGET_NR_semctl: +- ret = do_semctl(arg1, arg2, arg3, (union target_semun)(abi_ulong)arg4); +- break; +-#endif +-#ifdef TARGET_NR_msgctl +- case TARGET_NR_msgctl: +- ret = do_msgctl(arg1, arg2, arg3); +- break; +-#endif +-#ifdef TARGET_NR_msgget +- case TARGET_NR_msgget: +- ret = get_errno(msgget(arg1, arg2)); +- break; +-#endif +-#ifdef TARGET_NR_msgrcv +- case TARGET_NR_msgrcv: +- ret = do_msgrcv(arg1, arg2, arg3, arg4, arg5); +- break; +-#endif +-#ifdef TARGET_NR_msgsnd +- case TARGET_NR_msgsnd: +- ret = do_msgsnd(arg1, arg2, arg3, arg4); +- break; +-#endif +-#ifdef TARGET_NR_shmget +- case TARGET_NR_shmget: +- ret = get_errno(shmget(arg1, arg2, arg3)); +- break; +-#endif +-#ifdef TARGET_NR_shmctl +- case TARGET_NR_shmctl: +- ret = do_shmctl(arg1, arg2, arg3); +- break; +-#endif +-#ifdef TARGET_NR_shmat +- case TARGET_NR_shmat: +- ret = do_shmat(arg1, arg2, arg3); +- break; +-#endif +-#ifdef TARGET_NR_shmdt +- case TARGET_NR_shmdt: +- ret = do_shmdt(arg1); +- break; +-#endif +- case TARGET_NR_fsync: +- ret = get_errno(fsync(arg1)); +- break; +- case TARGET_NR_clone: +- /* Linux manages to have three different orderings for its +- * arguments to clone(); the BACKWARDS and BACKWARDS2 defines +- * match the kernel's CONFIG_CLONE_* settings. +- * Microblaze is further special in that it uses a sixth +- * implicit argument to clone for the TLS pointer. +- */ +-#if defined(TARGET_MICROBLAZE) +- ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5)); +-#elif defined(TARGET_CLONE_BACKWARDS) +- ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5)); +-#elif defined(TARGET_CLONE_BACKWARDS2) +- ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4)); +-#else +- ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4)); +-#endif +- break; +-#ifdef __NR_exit_group +- /* new thread calls */ +- case TARGET_NR_exit_group: +-#ifdef TARGET_GPROF +- _mcleanup(); +-#endif +- gdb_exit(cpu_env, arg1); +- ret = get_errno(exit_group(arg1)); +- break; +-#endif +- case TARGET_NR_setdomainname: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(setdomainname(p, arg2)); +- unlock_user(p, arg1, 0); +- break; +- case TARGET_NR_uname: +- /* no need to transcode because we use the linux syscall */ +- { +- struct new_utsname * buf; +- +- if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0)) +- goto efault; +- ret = get_errno(sys_uname(buf)); +- if (!is_error(ret)) { +- /* Overrite the native machine name with whatever is being +- emulated. */ +- strcpy (buf->machine, cpu_to_uname_machine(cpu_env)); +- /* Allow the user to override the reported release. */ +- if (qemu_uname_release && *qemu_uname_release) +- strcpy (buf->release, qemu_uname_release); +- } +- unlock_user_struct(buf, arg1, 1); +- } +- break; +-#ifdef TARGET_I386 +- case TARGET_NR_modify_ldt: +- ret = do_modify_ldt(cpu_env, arg1, arg2, arg3); +- break; +-#if !defined(TARGET_X86_64) +- case TARGET_NR_vm86old: +- goto unimplemented; +- case TARGET_NR_vm86: +- ret = do_vm86(cpu_env, arg1, arg2); +- break; +-#endif +-#endif +- case TARGET_NR_adjtimex: +- goto unimplemented; +-#ifdef TARGET_NR_create_module +- case TARGET_NR_create_module: +-#endif +- case TARGET_NR_init_module: +- case TARGET_NR_delete_module: +-#ifdef TARGET_NR_get_kernel_syms +- case TARGET_NR_get_kernel_syms: +-#endif +- goto unimplemented; +- case TARGET_NR_quotactl: +- goto unimplemented; +- case TARGET_NR_getpgid: +- ret = get_errno(getpgid(arg1)); +- break; +- case TARGET_NR_fchdir: +- ret = get_errno(fchdir(arg1)); +- break; +-#ifdef TARGET_NR_bdflush /* not on x86_64 */ +- case TARGET_NR_bdflush: +- goto unimplemented; +-#endif +-#ifdef TARGET_NR_sysfs +- case TARGET_NR_sysfs: +- goto unimplemented; +-#endif +- case TARGET_NR_personality: +- ret = get_errno(personality(arg1)); +- break; +-#ifdef TARGET_NR_afs_syscall +- case TARGET_NR_afs_syscall: +- goto unimplemented; +-#endif +-#ifdef TARGET_NR__llseek /* Not on alpha */ +- case TARGET_NR__llseek: +- { +- int64_t res; +-#if !defined(__NR_llseek) +- res = lseek(arg1, ((uint64_t)arg2 << 32) | arg3, arg5); +- if (res == -1) { +- ret = get_errno(res); +- } else { +- ret = 0; +- } +-#else +- ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5)); +-#endif +- if ((ret == 0) && put_user_s64(res, arg4)) { +- goto efault; +- } +- } +- break; +-#endif +- case TARGET_NR_getdents: +-#ifdef __NR_getdents +-#if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64 +- { +- struct target_dirent *target_dirp; +- struct linux_dirent *dirp; +- abi_long count = arg3; +- +- dirp = malloc(count); +- if (!dirp) { +- ret = -TARGET_ENOMEM; +- goto fail; +- } +- +- ret = get_errno(sys_getdents(arg1, dirp, count)); +- if (!is_error(ret)) { +- struct linux_dirent *de; +- struct target_dirent *tde; +- int len = ret; +- int reclen, treclen; +- int count1, tnamelen; +- +- count1 = 0; +- de = dirp; +- if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0))) +- goto efault; +- tde = target_dirp; +- while (len > 0) { +- reclen = de->d_reclen; +- tnamelen = reclen - offsetof(struct linux_dirent, d_name); +- assert(tnamelen >= 0); +- treclen = tnamelen + offsetof(struct target_dirent, d_name); +- assert(count1 + treclen <= count); +- tde->d_reclen = tswap16(treclen); +- tde->d_ino = tswapal(de->d_ino); +- tde->d_off = tswapal(de->d_off); +- memcpy(tde->d_name, de->d_name, tnamelen); +- de = (struct linux_dirent *)((char *)de + reclen); +- len -= reclen; +- tde = (struct target_dirent *)((char *)tde + treclen); +- count1 += treclen; +- } +- ret = count1; +- unlock_user(target_dirp, arg2, ret); +- } +- free(dirp); +- } +-#else +- { +- struct linux_dirent *dirp; +- abi_long count = arg3; +- +- if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0))) +- goto efault; +- ret = get_errno(sys_getdents(arg1, dirp, count)); +- if (!is_error(ret)) { +- struct linux_dirent *de; +- int len = ret; +- int reclen; +- de = dirp; +- while (len > 0) { +- reclen = de->d_reclen; +- if (reclen > len) +- break; +- de->d_reclen = tswap16(reclen); +- tswapls(&de->d_ino); +- tswapls(&de->d_off); +- de = (struct linux_dirent *)((char *)de + reclen); +- len -= reclen; +- } +- } +- unlock_user(dirp, arg2, ret); +- } +-#endif +-#else +- /* Implement getdents in terms of getdents64 */ +- { +- struct linux_dirent64 *dirp; +- abi_long count = arg3; +- +- dirp = lock_user(VERIFY_WRITE, arg2, count, 0); +- if (!dirp) { +- goto efault; +- } +- ret = get_errno(sys_getdents64(arg1, dirp, count)); +- if (!is_error(ret)) { +- /* Convert the dirent64 structs to target dirent. We do this +- * in-place, since we can guarantee that a target_dirent is no +- * larger than a dirent64; however this means we have to be +- * careful to read everything before writing in the new format. +- */ +- struct linux_dirent64 *de; +- struct target_dirent *tde; +- int len = ret; +- int tlen = 0; +- +- de = dirp; +- tde = (struct target_dirent *)dirp; +- while (len > 0) { +- int namelen, treclen; +- int reclen = de->d_reclen; +- uint64_t ino = de->d_ino; +- int64_t off = de->d_off; +- uint8_t type = de->d_type; +- +- namelen = strlen(de->d_name); +- treclen = offsetof(struct target_dirent, d_name) +- + namelen + 2; +- treclen = QEMU_ALIGN_UP(treclen, sizeof(abi_long)); +- +- memmove(tde->d_name, de->d_name, namelen + 1); +- tde->d_ino = tswapal(ino); +- tde->d_off = tswapal(off); +- tde->d_reclen = tswap16(treclen); +- /* The target_dirent type is in what was formerly a padding +- * byte at the end of the structure: +- */ +- *(((char *)tde) + treclen - 1) = type; +- +- de = (struct linux_dirent64 *)((char *)de + reclen); +- tde = (struct target_dirent *)((char *)tde + treclen); +- len -= reclen; +- tlen += treclen; +- } +- ret = tlen; +- } +- unlock_user(dirp, arg2, ret); +- } +-#endif +- break; +-#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64) +- case TARGET_NR_getdents64: +- { +- struct linux_dirent64 *dirp; +- abi_long count = arg3; +- if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0))) +- goto efault; +- ret = get_errno(sys_getdents64(arg1, dirp, count)); +- if (!is_error(ret)) { +- struct linux_dirent64 *de; +- int len = ret; +- int reclen; +- de = dirp; +- while (len > 0) { +- reclen = de->d_reclen; +- if (reclen > len) +- break; +- de->d_reclen = tswap16(reclen); +- tswap64s((uint64_t *)&de->d_ino); +- tswap64s((uint64_t *)&de->d_off); +- de = (struct linux_dirent64 *)((char *)de + reclen); +- len -= reclen; +- } +- } +- unlock_user(dirp, arg2, ret); +- } +- break; +-#endif /* TARGET_NR_getdents64 */ +-#if defined(TARGET_NR__newselect) +- case TARGET_NR__newselect: +- ret = do_select(arg1, arg2, arg3, arg4, arg5); +- break; +-#endif +-#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll) +-# ifdef TARGET_NR_poll +- case TARGET_NR_poll: +-# endif +-# ifdef TARGET_NR_ppoll +- case TARGET_NR_ppoll: +-# endif +- { +- struct target_pollfd *target_pfd; +- unsigned int nfds = arg2; +- int timeout = arg3; +- struct pollfd *pfd; +- unsigned int i; +- +- target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1); +- if (!target_pfd) +- goto efault; +- +- pfd = alloca(sizeof(struct pollfd) * nfds); +- for(i = 0; i < nfds; i++) { +- pfd[i].fd = tswap32(target_pfd[i].fd); +- pfd[i].events = tswap16(target_pfd[i].events); +- } +- +-# ifdef TARGET_NR_ppoll +- if (num == TARGET_NR_ppoll) { +- struct timespec _timeout_ts, *timeout_ts = &_timeout_ts; +- target_sigset_t *target_set; +- sigset_t _set, *set = &_set; +- +- if (arg3) { +- if (target_to_host_timespec(timeout_ts, arg3)) { +- unlock_user(target_pfd, arg1, 0); +- goto efault; +- } +- } else { +- timeout_ts = NULL; +- } +- +- if (arg4) { +- target_set = lock_user(VERIFY_READ, arg4, sizeof(target_sigset_t), 1); +- if (!target_set) { +- unlock_user(target_pfd, arg1, 0); +- goto efault; +- } +- target_to_host_sigset(set, target_set); +- } else { +- set = NULL; +- } +- +- ret = get_errno(sys_ppoll(pfd, nfds, timeout_ts, set, _NSIG/8)); +- +- if (!is_error(ret) && arg3) { +- host_to_target_timespec(arg3, timeout_ts); +- } +- if (arg4) { +- unlock_user(target_set, arg4, 0); +- } +- } else +-# endif +- ret = get_errno(poll(pfd, nfds, timeout)); +- +- if (!is_error(ret)) { +- for(i = 0; i < nfds; i++) { +- target_pfd[i].revents = tswap16(pfd[i].revents); +- } +- } +- unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds); +- } +- break; +-#endif +- case TARGET_NR_flock: +- /* NOTE: the flock constant seems to be the same for every +- Linux platform */ +- ret = get_errno(flock(arg1, arg2)); +- break; +- case TARGET_NR_readv: +- { +- struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0); +- if (vec != NULL) { +- ret = get_errno(readv(arg1, vec, arg3)); +- unlock_iovec(vec, arg2, arg3, 1); +- } else { +- ret = -host_to_target_errno(errno); +- } +- } +- break; +- case TARGET_NR_writev: +- { +- struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1); +- if (vec != NULL) { +- ret = get_errno(writev(arg1, vec, arg3)); +- unlock_iovec(vec, arg2, arg3, 0); +- } else { +- ret = -host_to_target_errno(errno); +- } +- } +- break; +- case TARGET_NR_getsid: +- ret = get_errno(getsid(arg1)); +- break; +-#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */ +- case TARGET_NR_fdatasync: +- ret = get_errno(fdatasync(arg1)); +- break; +-#endif +- case TARGET_NR__sysctl: +- /* We don't implement this, but ENOTDIR is always a safe +- return value. */ +- ret = -TARGET_ENOTDIR; +- break; +- case TARGET_NR_sched_getaffinity: +- { +- unsigned int mask_size; +- unsigned long *mask; +- +- /* +- * sched_getaffinity needs multiples of ulong, so need to take +- * care of mismatches between target ulong and host ulong sizes. +- */ +- if (arg2 & (sizeof(abi_ulong) - 1)) { +- ret = -TARGET_EINVAL; +- break; +- } +- mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1); +- +- mask = alloca(mask_size); +- ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask)); +- +- if (!is_error(ret)) { +- if (ret > arg2) { +- /* More data returned than the caller's buffer will fit. +- * This only happens if sizeof(abi_long) < sizeof(long) +- * and the caller passed us a buffer holding an odd number +- * of abi_longs. If the host kernel is actually using the +- * extra 4 bytes then fail EINVAL; otherwise we can just +- * ignore them and only copy the interesting part. +- */ +- int numcpus = sysconf(_SC_NPROCESSORS_CONF); +- if (numcpus > arg2 * 8) { +- ret = -TARGET_EINVAL; +- break; +- } +- ret = arg2; +- } +- +- if (copy_to_user(arg3, mask, ret)) { +- goto efault; +- } +- } +- } +- break; +- case TARGET_NR_sched_setaffinity: +- { +- unsigned int mask_size; +- unsigned long *mask; +- +- /* +- * sched_setaffinity needs multiples of ulong, so need to take +- * care of mismatches between target ulong and host ulong sizes. +- */ +- if (arg2 & (sizeof(abi_ulong) - 1)) { +- ret = -TARGET_EINVAL; +- break; +- } +- mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1); +- +- mask = alloca(mask_size); +- if (!lock_user_struct(VERIFY_READ, p, arg3, 1)) { +- goto efault; +- } +- memcpy(mask, p, arg2); +- unlock_user_struct(p, arg2, 0); +- +- ret = get_errno(sys_sched_setaffinity(arg1, mask_size, mask)); +- } +- break; +- case TARGET_NR_sched_setparam: +- { +- struct sched_param *target_schp; +- struct sched_param schp; +- +- if (arg2 == 0) { +- return -TARGET_EINVAL; +- } +- if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1)) +- goto efault; +- schp.sched_priority = tswap32(target_schp->sched_priority); +- unlock_user_struct(target_schp, arg2, 0); +- ret = get_errno(sched_setparam(arg1, &schp)); +- } +- break; +- case TARGET_NR_sched_getparam: +- { +- struct sched_param *target_schp; +- struct sched_param schp; +- +- if (arg2 == 0) { +- return -TARGET_EINVAL; +- } +- ret = get_errno(sched_getparam(arg1, &schp)); +- if (!is_error(ret)) { +- if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0)) +- goto efault; +- target_schp->sched_priority = tswap32(schp.sched_priority); +- unlock_user_struct(target_schp, arg2, 1); +- } +- } +- break; +- case TARGET_NR_sched_setscheduler: +- { +- struct sched_param *target_schp; +- struct sched_param schp; +- if (arg3 == 0) { +- return -TARGET_EINVAL; +- } +- if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1)) +- goto efault; +- schp.sched_priority = tswap32(target_schp->sched_priority); +- unlock_user_struct(target_schp, arg3, 0); +- ret = get_errno(sched_setscheduler(arg1, arg2, &schp)); +- } +- break; +- case TARGET_NR_sched_getscheduler: +- ret = get_errno(sched_getscheduler(arg1)); +- break; +- case TARGET_NR_sched_yield: +- ret = get_errno(sched_yield()); +- break; +- case TARGET_NR_sched_get_priority_max: +- ret = get_errno(sched_get_priority_max(arg1)); +- break; +- case TARGET_NR_sched_get_priority_min: +- ret = get_errno(sched_get_priority_min(arg1)); +- break; +- case TARGET_NR_sched_rr_get_interval: +- { +- struct timespec ts; +- ret = get_errno(sched_rr_get_interval(arg1, &ts)); +- if (!is_error(ret)) { +- ret = host_to_target_timespec(arg2, &ts); +- } +- } +- break; +- case TARGET_NR_nanosleep: +- { +- struct timespec req, rem; +- target_to_host_timespec(&req, arg1); +- ret = get_errno(nanosleep(&req, &rem)); +- if (is_error(ret) && arg2) { +- host_to_target_timespec(arg2, &rem); +- } +- } +- break; +-#ifdef TARGET_NR_query_module +- case TARGET_NR_query_module: +- goto unimplemented; +-#endif +-#ifdef TARGET_NR_nfsservctl +- case TARGET_NR_nfsservctl: +- goto unimplemented; +-#endif +- case TARGET_NR_prctl: +- switch (arg1) { +- case PR_GET_PDEATHSIG: +- { +- int deathsig; +- ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5)); +- if (!is_error(ret) && arg2 +- && put_user_ual(deathsig, arg2)) { +- goto efault; +- } +- break; +- } +-#ifdef PR_GET_NAME +- case PR_GET_NAME: +- { +- void *name = lock_user(VERIFY_WRITE, arg2, 16, 1); +- if (!name) { +- goto efault; +- } +- ret = get_errno(prctl(arg1, (unsigned long)name, +- arg3, arg4, arg5)); +- unlock_user(name, arg2, 16); +- break; +- } +- case PR_SET_NAME: +- { +- void *name = lock_user(VERIFY_READ, arg2, 16, 1); +- if (!name) { +- goto efault; +- } +- ret = get_errno(prctl(arg1, (unsigned long)name, +- arg3, arg4, arg5)); +- unlock_user(name, arg2, 0); +- break; +- } +-#endif +- default: +- /* Most prctl options have no pointer arguments */ +- ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5)); +- break; +- } +- break; +-#ifdef TARGET_NR_arch_prctl +- case TARGET_NR_arch_prctl: +-#if defined(TARGET_I386) && !defined(TARGET_ABI32) +- ret = do_arch_prctl(cpu_env, arg1, arg2); +- break; +-#else +- goto unimplemented; +-#endif +-#endif +-#ifdef TARGET_NR_pread64 +- case TARGET_NR_pread64: +- if (regpairs_aligned(cpu_env)) { +- arg4 = arg5; +- arg5 = arg6; +- } +- if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0))) +- goto efault; +- ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5))); +- unlock_user(p, arg2, ret); +- break; +- case TARGET_NR_pwrite64: +- if (regpairs_aligned(cpu_env)) { +- arg4 = arg5; +- arg5 = arg6; +- } +- if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1))) +- goto efault; +- ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5))); +- unlock_user(p, arg2, 0); +- break; +-#endif +- case TARGET_NR_getcwd: +- if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0))) +- goto efault; +- ret = get_errno(sys_getcwd1(p, arg2)); +- unlock_user(p, arg1, ret); +- break; +- case TARGET_NR_capget: +- case TARGET_NR_capset: +- { +- struct target_user_cap_header *target_header; +- struct target_user_cap_data *target_data = NULL; +- struct __user_cap_header_struct header; +- struct __user_cap_data_struct data[2]; +- struct __user_cap_data_struct *dataptr = NULL; +- int i, target_datalen; +- int data_items = 1; +- +- if (!lock_user_struct(VERIFY_WRITE, target_header, arg1, 1)) { +- goto efault; +- } +- header.version = tswap32(target_header->version); +- header.pid = tswap32(target_header->pid); +- +- if (header.version != _LINUX_CAPABILITY_VERSION) { +- /* Version 2 and up takes pointer to two user_data structs */ +- data_items = 2; +- } +- +- target_datalen = sizeof(*target_data) * data_items; +- +- if (arg2) { +- if (num == TARGET_NR_capget) { +- target_data = lock_user(VERIFY_WRITE, arg2, target_datalen, 0); +- } else { +- target_data = lock_user(VERIFY_READ, arg2, target_datalen, 1); +- } +- if (!target_data) { +- unlock_user_struct(target_header, arg1, 0); +- goto efault; +- } +- +- if (num == TARGET_NR_capset) { +- for (i = 0; i < data_items; i++) { +- data[i].effective = tswap32(target_data[i].effective); +- data[i].permitted = tswap32(target_data[i].permitted); +- data[i].inheritable = tswap32(target_data[i].inheritable); +- } +- } +- +- dataptr = data; +- } +- +- if (num == TARGET_NR_capget) { +- ret = get_errno(capget(&header, dataptr)); +- } else { +- ret = get_errno(capset(&header, dataptr)); +- } +- +- /* The kernel always updates version for both capget and capset */ +- target_header->version = tswap32(header.version); +- unlock_user_struct(target_header, arg1, 1); +- +- if (arg2) { +- if (num == TARGET_NR_capget) { +- for (i = 0; i < data_items; i++) { +- target_data[i].effective = tswap32(data[i].effective); +- target_data[i].permitted = tswap32(data[i].permitted); +- target_data[i].inheritable = tswap32(data[i].inheritable); +- } +- unlock_user(target_data, arg2, target_datalen); +- } else { +- unlock_user(target_data, arg2, 0); +- } +- } +- break; +- } +- case TARGET_NR_sigaltstack: +-#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \ +- defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA) || \ +- defined(TARGET_M68K) || defined(TARGET_S390X) || defined(TARGET_OPENRISC) +- ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUArchState *)cpu_env)); +- break; +-#else +- goto unimplemented; +-#endif +- +-#ifdef CONFIG_SENDFILE +- case TARGET_NR_sendfile: +- { +- off_t *offp = NULL; +- off_t off; +- if (arg3) { +- ret = get_user_sal(off, arg3); +- if (is_error(ret)) { +- break; +- } +- offp = &off; +- } +- ret = get_errno(sendfile(arg1, arg2, offp, arg4)); +- if (!is_error(ret) && arg3) { +- abi_long ret2 = put_user_sal(off, arg3); +- if (is_error(ret2)) { +- ret = ret2; +- } +- } +- break; +- } +-#ifdef TARGET_NR_sendfile64 +- case TARGET_NR_sendfile64: +- { +- off_t *offp = NULL; +- off_t off; +- if (arg3) { +- ret = get_user_s64(off, arg3); +- if (is_error(ret)) { +- break; +- } +- offp = &off; +- } +- ret = get_errno(sendfile(arg1, arg2, offp, arg4)); +- if (!is_error(ret) && arg3) { +- abi_long ret2 = put_user_s64(off, arg3); +- if (is_error(ret2)) { +- ret = ret2; +- } +- } +- break; +- } +-#endif +-#else +- case TARGET_NR_sendfile: +-#ifdef TARGET_NR_sendfile64 +- case TARGET_NR_sendfile64: +-#endif +- goto unimplemented; +-#endif +- +-#ifdef TARGET_NR_getpmsg +- case TARGET_NR_getpmsg: +- goto unimplemented; +-#endif +-#ifdef TARGET_NR_putpmsg +- case TARGET_NR_putpmsg: +- goto unimplemented; +-#endif +-#ifdef TARGET_NR_vfork +- case TARGET_NR_vfork: +- ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, +- 0, 0, 0, 0)); +- break; +-#endif +-#ifdef TARGET_NR_ugetrlimit +- case TARGET_NR_ugetrlimit: +- { +- struct rlimit rlim; +- int resource = target_to_host_resource(arg1); +- ret = get_errno(getrlimit(resource, &rlim)); +- if (!is_error(ret)) { +- struct target_rlimit *target_rlim; +- if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0)) +- goto efault; +- target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur); +- target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max); +- unlock_user_struct(target_rlim, arg2, 1); +- } +- break; +- } +-#endif +-#ifdef TARGET_NR_truncate64 +- case TARGET_NR_truncate64: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = target_truncate64(cpu_env, p, arg2, arg3, arg4); +- unlock_user(p, arg1, 0); +- break; +-#endif +-#ifdef TARGET_NR_ftruncate64 +- case TARGET_NR_ftruncate64: +- ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4); +- break; +-#endif +-#ifdef TARGET_NR_stat64 +- case TARGET_NR_stat64: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(stat(path(p), &st)); +- unlock_user(p, arg1, 0); +- if (!is_error(ret)) +- ret = host_to_target_stat64(cpu_env, arg2, &st); +- break; +-#endif +-#ifdef TARGET_NR_lstat64 +- case TARGET_NR_lstat64: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(lstat(path(p), &st)); +- unlock_user(p, arg1, 0); +- if (!is_error(ret)) +- ret = host_to_target_stat64(cpu_env, arg2, &st); +- break; +-#endif +-#ifdef TARGET_NR_fstat64 +- case TARGET_NR_fstat64: +- ret = get_errno(fstat(arg1, &st)); +- if (!is_error(ret)) +- ret = host_to_target_stat64(cpu_env, arg2, &st); +- break; +-#endif +-#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) +-#ifdef TARGET_NR_fstatat64 +- case TARGET_NR_fstatat64: +-#endif +-#ifdef TARGET_NR_newfstatat +- case TARGET_NR_newfstatat: +-#endif +- if (!(p = lock_user_string(arg2))) +- goto efault; +- ret = get_errno(fstatat(arg1, path(p), &st, arg4)); +- if (!is_error(ret)) +- ret = host_to_target_stat64(cpu_env, arg3, &st); +- break; +-#endif +- case TARGET_NR_lchown: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3))); +- unlock_user(p, arg1, 0); +- break; +-#ifdef TARGET_NR_getuid +- case TARGET_NR_getuid: +- ret = get_errno(high2lowuid(getuid())); +- break; +-#endif +-#ifdef TARGET_NR_getgid +- case TARGET_NR_getgid: +- ret = get_errno(high2lowgid(getgid())); +- break; +-#endif +-#ifdef TARGET_NR_geteuid +- case TARGET_NR_geteuid: +- ret = get_errno(high2lowuid(geteuid())); +- break; +-#endif +-#ifdef TARGET_NR_getegid +- case TARGET_NR_getegid: +- ret = get_errno(high2lowgid(getegid())); +- break; +-#endif +- case TARGET_NR_setreuid: +- ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2))); +- break; +- case TARGET_NR_setregid: +- ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2))); +- break; +- case TARGET_NR_getgroups: +- { +- int gidsetsize = arg1; +- target_id *target_grouplist; +- gid_t *grouplist; +- int i; +- +- grouplist = alloca(gidsetsize * sizeof(gid_t)); +- ret = get_errno(getgroups(gidsetsize, grouplist)); +- if (gidsetsize == 0) +- break; +- if (!is_error(ret)) { +- target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * sizeof(target_id), 0); +- if (!target_grouplist) +- goto efault; +- for(i = 0;i < ret; i++) +- target_grouplist[i] = tswapid(high2lowgid(grouplist[i])); +- unlock_user(target_grouplist, arg2, gidsetsize * sizeof(target_id)); +- } +- } +- break; +- case TARGET_NR_setgroups: +- { +- int gidsetsize = arg1; +- target_id *target_grouplist; +- gid_t *grouplist = NULL; +- int i; +- if (gidsetsize) { +- grouplist = alloca(gidsetsize * sizeof(gid_t)); +- target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * sizeof(target_id), 1); +- if (!target_grouplist) { +- ret = -TARGET_EFAULT; +- goto fail; +- } +- for (i = 0; i < gidsetsize; i++) { +- grouplist[i] = low2highgid(tswapid(target_grouplist[i])); +- } +- unlock_user(target_grouplist, arg2, 0); +- } +- ret = get_errno(setgroups(gidsetsize, grouplist)); +- } +- break; +- case TARGET_NR_fchown: +- ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3))); +- break; +-#if defined(TARGET_NR_fchownat) +- case TARGET_NR_fchownat: +- if (!(p = lock_user_string(arg2))) +- goto efault; +- ret = get_errno(fchownat(arg1, p, low2highuid(arg3), +- low2highgid(arg4), arg5)); +- unlock_user(p, arg2, 0); +- break; +-#endif +-#ifdef TARGET_NR_setresuid +- case TARGET_NR_setresuid: +- ret = get_errno(setresuid(low2highuid(arg1), +- low2highuid(arg2), +- low2highuid(arg3))); +- break; +-#endif +-#ifdef TARGET_NR_getresuid +- case TARGET_NR_getresuid: +- { +- uid_t ruid, euid, suid; +- ret = get_errno(getresuid(&ruid, &euid, &suid)); +- if (!is_error(ret)) { +- if (put_user_id(high2lowuid(ruid), arg1) +- || put_user_id(high2lowuid(euid), arg2) +- || put_user_id(high2lowuid(suid), arg3)) +- goto efault; +- } +- } +- break; +-#endif +-#ifdef TARGET_NR_getresgid +- case TARGET_NR_setresgid: +- ret = get_errno(setresgid(low2highgid(arg1), +- low2highgid(arg2), +- low2highgid(arg3))); +- break; +-#endif +-#ifdef TARGET_NR_getresgid +- case TARGET_NR_getresgid: +- { +- gid_t rgid, egid, sgid; +- ret = get_errno(getresgid(&rgid, &egid, &sgid)); +- if (!is_error(ret)) { +- if (put_user_id(high2lowgid(rgid), arg1) +- || put_user_id(high2lowgid(egid), arg2) +- || put_user_id(high2lowgid(sgid), arg3)) +- goto efault; +- } +- } +- break; +-#endif +- case TARGET_NR_chown: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3))); +- unlock_user(p, arg1, 0); +- break; +- case TARGET_NR_setuid: +- ret = get_errno(setuid(low2highuid(arg1))); +- break; +- case TARGET_NR_setgid: +- ret = get_errno(setgid(low2highgid(arg1))); +- break; +- case TARGET_NR_setfsuid: +- ret = get_errno(setfsuid(arg1)); +- break; +- case TARGET_NR_setfsgid: +- ret = get_errno(setfsgid(arg1)); +- break; +- +-#ifdef TARGET_NR_lchown32 +- case TARGET_NR_lchown32: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(lchown(p, arg2, arg3)); +- unlock_user(p, arg1, 0); +- break; +-#endif +-#ifdef TARGET_NR_getuid32 +- case TARGET_NR_getuid32: +- ret = get_errno(getuid()); +- break; +-#endif +- +-#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA) +- /* Alpha specific */ +- case TARGET_NR_getxuid: +- { +- uid_t euid; +- euid=geteuid(); +- ((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid; +- } +- ret = get_errno(getuid()); +- break; +-#endif +-#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA) +- /* Alpha specific */ +- case TARGET_NR_getxgid: +- { +- uid_t egid; +- egid=getegid(); +- ((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid; +- } +- ret = get_errno(getgid()); +- break; +-#endif +-#if defined(TARGET_NR_osf_getsysinfo) && defined(TARGET_ALPHA) +- /* Alpha specific */ +- case TARGET_NR_osf_getsysinfo: +- ret = -TARGET_EOPNOTSUPP; +- switch (arg1) { +- case TARGET_GSI_IEEE_FP_CONTROL: +- { +- uint64_t swcr, fpcr = cpu_alpha_load_fpcr (cpu_env); +- +- /* Copied from linux ieee_fpcr_to_swcr. */ +- swcr = (fpcr >> 35) & SWCR_STATUS_MASK; +- swcr |= (fpcr >> 36) & SWCR_MAP_DMZ; +- swcr |= (~fpcr >> 48) & (SWCR_TRAP_ENABLE_INV +- | SWCR_TRAP_ENABLE_DZE +- | SWCR_TRAP_ENABLE_OVF); +- swcr |= (~fpcr >> 57) & (SWCR_TRAP_ENABLE_UNF +- | SWCR_TRAP_ENABLE_INE); +- swcr |= (fpcr >> 47) & SWCR_MAP_UMZ; +- swcr |= (~fpcr >> 41) & SWCR_TRAP_ENABLE_DNO; +- +- if (put_user_u64 (swcr, arg2)) +- goto efault; +- ret = 0; +- } +- break; +- +- /* case GSI_IEEE_STATE_AT_SIGNAL: +- -- Not implemented in linux kernel. +- case GSI_UACPROC: +- -- Retrieves current unaligned access state; not much used. +- case GSI_PROC_TYPE: +- -- Retrieves implver information; surely not used. +- case GSI_GET_HWRPB: +- -- Grabs a copy of the HWRPB; surely not used. +- */ +- } +- break; +-#endif +-#if defined(TARGET_NR_osf_setsysinfo) && defined(TARGET_ALPHA) +- /* Alpha specific */ +- case TARGET_NR_osf_setsysinfo: +- ret = -TARGET_EOPNOTSUPP; +- switch (arg1) { +- case TARGET_SSI_IEEE_FP_CONTROL: +- { +- uint64_t swcr, fpcr, orig_fpcr; +- +- if (get_user_u64 (swcr, arg2)) { +- goto efault; +- } +- orig_fpcr = cpu_alpha_load_fpcr(cpu_env); +- fpcr = orig_fpcr & FPCR_DYN_MASK; +- +- /* Copied from linux ieee_swcr_to_fpcr. */ +- fpcr |= (swcr & SWCR_STATUS_MASK) << 35; +- fpcr |= (swcr & SWCR_MAP_DMZ) << 36; +- fpcr |= (~swcr & (SWCR_TRAP_ENABLE_INV +- | SWCR_TRAP_ENABLE_DZE +- | SWCR_TRAP_ENABLE_OVF)) << 48; +- fpcr |= (~swcr & (SWCR_TRAP_ENABLE_UNF +- | SWCR_TRAP_ENABLE_INE)) << 57; +- fpcr |= (swcr & SWCR_MAP_UMZ ? FPCR_UNDZ | FPCR_UNFD : 0); +- fpcr |= (~swcr & SWCR_TRAP_ENABLE_DNO) << 41; +- +- cpu_alpha_store_fpcr(cpu_env, fpcr); +- ret = 0; +- } +- break; +- +- case TARGET_SSI_IEEE_RAISE_EXCEPTION: +- { +- uint64_t exc, fpcr, orig_fpcr; +- int si_code; +- +- if (get_user_u64(exc, arg2)) { +- goto efault; +- } +- +- orig_fpcr = cpu_alpha_load_fpcr(cpu_env); +- +- /* We only add to the exception status here. */ +- fpcr = orig_fpcr | ((exc & SWCR_STATUS_MASK) << 35); +- +- cpu_alpha_store_fpcr(cpu_env, fpcr); +- ret = 0; +- +- /* Old exceptions are not signaled. */ +- fpcr &= ~(orig_fpcr & FPCR_STATUS_MASK); +- +- /* If any exceptions set by this call, +- and are unmasked, send a signal. */ +- si_code = 0; +- if ((fpcr & (FPCR_INE | FPCR_INED)) == FPCR_INE) { +- si_code = TARGET_FPE_FLTRES; +- } +- if ((fpcr & (FPCR_UNF | FPCR_UNFD)) == FPCR_UNF) { +- si_code = TARGET_FPE_FLTUND; +- } +- if ((fpcr & (FPCR_OVF | FPCR_OVFD)) == FPCR_OVF) { +- si_code = TARGET_FPE_FLTOVF; +- } +- if ((fpcr & (FPCR_DZE | FPCR_DZED)) == FPCR_DZE) { +- si_code = TARGET_FPE_FLTDIV; +- } +- if ((fpcr & (FPCR_INV | FPCR_INVD)) == FPCR_INV) { +- si_code = TARGET_FPE_FLTINV; +- } +- if (si_code != 0) { +- target_siginfo_t info; +- info.si_signo = SIGFPE; +- info.si_errno = 0; +- info.si_code = si_code; +- info._sifields._sigfault._addr +- = ((CPUArchState *)cpu_env)->pc; +- queue_signal((CPUArchState *)cpu_env, info.si_signo, &info); +- } +- } +- break; +- +- /* case SSI_NVPAIRS: +- -- Used with SSIN_UACPROC to enable unaligned accesses. +- case SSI_IEEE_STATE_AT_SIGNAL: +- case SSI_IEEE_IGNORE_STATE_AT_SIGNAL: +- -- Not implemented in linux kernel +- */ +- } +- break; +-#endif +-#ifdef TARGET_NR_osf_sigprocmask +- /* Alpha specific. */ +- case TARGET_NR_osf_sigprocmask: +- { +- abi_ulong mask; +- int how; +- sigset_t set, oldset; +- +- switch(arg1) { +- case TARGET_SIG_BLOCK: +- how = SIG_BLOCK; +- break; +- case TARGET_SIG_UNBLOCK: +- how = SIG_UNBLOCK; +- break; +- case TARGET_SIG_SETMASK: +- how = SIG_SETMASK; +- break; +- default: +- ret = -TARGET_EINVAL; +- goto fail; +- } +- mask = arg2; +- target_to_host_old_sigset(&set, &mask); +- do_sigprocmask(how, &set, &oldset); +- host_to_target_old_sigset(&mask, &oldset); +- ret = mask; +- } +- break; +-#endif +- +-#ifdef TARGET_NR_getgid32 +- case TARGET_NR_getgid32: +- ret = get_errno(getgid()); +- break; +-#endif +-#ifdef TARGET_NR_geteuid32 +- case TARGET_NR_geteuid32: +- ret = get_errno(geteuid()); +- break; +-#endif +-#ifdef TARGET_NR_getegid32 +- case TARGET_NR_getegid32: +- ret = get_errno(getegid()); +- break; +-#endif +-#ifdef TARGET_NR_setreuid32 +- case TARGET_NR_setreuid32: +- ret = get_errno(setreuid(arg1, arg2)); +- break; +-#endif +-#ifdef TARGET_NR_setregid32 +- case TARGET_NR_setregid32: +- ret = get_errno(setregid(arg1, arg2)); +- break; +-#endif +-#ifdef TARGET_NR_getgroups32 +- case TARGET_NR_getgroups32: +- { +- int gidsetsize = arg1; +- uint32_t *target_grouplist; +- gid_t *grouplist; +- int i; +- +- grouplist = alloca(gidsetsize * sizeof(gid_t)); +- ret = get_errno(getgroups(gidsetsize, grouplist)); +- if (gidsetsize == 0) +- break; +- if (!is_error(ret)) { +- target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0); +- if (!target_grouplist) { +- ret = -TARGET_EFAULT; +- goto fail; +- } +- for(i = 0;i < ret; i++) +- target_grouplist[i] = tswap32(grouplist[i]); +- unlock_user(target_grouplist, arg2, gidsetsize * 4); +- } +- } +- break; +-#endif +-#ifdef TARGET_NR_setgroups32 +- case TARGET_NR_setgroups32: +- { +- int gidsetsize = arg1; +- uint32_t *target_grouplist; +- gid_t *grouplist; +- int i; +- +- grouplist = alloca(gidsetsize * sizeof(gid_t)); +- target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1); +- if (!target_grouplist) { +- ret = -TARGET_EFAULT; +- goto fail; +- } +- for(i = 0;i < gidsetsize; i++) +- grouplist[i] = tswap32(target_grouplist[i]); +- unlock_user(target_grouplist, arg2, 0); +- ret = get_errno(setgroups(gidsetsize, grouplist)); +- } +- break; +-#endif +-#ifdef TARGET_NR_fchown32 +- case TARGET_NR_fchown32: +- ret = get_errno(fchown(arg1, arg2, arg3)); +- break; +-#endif +-#ifdef TARGET_NR_setresuid32 +- case TARGET_NR_setresuid32: +- ret = get_errno(setresuid(arg1, arg2, arg3)); +- break; +-#endif +-#ifdef TARGET_NR_getresuid32 +- case TARGET_NR_getresuid32: +- { +- uid_t ruid, euid, suid; +- ret = get_errno(getresuid(&ruid, &euid, &suid)); +- if (!is_error(ret)) { +- if (put_user_u32(ruid, arg1) +- || put_user_u32(euid, arg2) +- || put_user_u32(suid, arg3)) +- goto efault; +- } +- } +- break; +-#endif +-#ifdef TARGET_NR_setresgid32 +- case TARGET_NR_setresgid32: +- ret = get_errno(setresgid(arg1, arg2, arg3)); +- break; +-#endif +-#ifdef TARGET_NR_getresgid32 +- case TARGET_NR_getresgid32: +- { +- gid_t rgid, egid, sgid; +- ret = get_errno(getresgid(&rgid, &egid, &sgid)); +- if (!is_error(ret)) { +- if (put_user_u32(rgid, arg1) +- || put_user_u32(egid, arg2) +- || put_user_u32(sgid, arg3)) +- goto efault; +- } +- } +- break; +-#endif +-#ifdef TARGET_NR_chown32 +- case TARGET_NR_chown32: +- if (!(p = lock_user_string(arg1))) +- goto efault; +- ret = get_errno(chown(p, arg2, arg3)); +- unlock_user(p, arg1, 0); +- break; +-#endif +-#ifdef TARGET_NR_setuid32 +- case TARGET_NR_setuid32: +- ret = get_errno(setuid(arg1)); +- break; +-#endif +-#ifdef TARGET_NR_setgid32 +- case TARGET_NR_setgid32: +- ret = get_errno(setgid(arg1)); +- break; +-#endif +-#ifdef TARGET_NR_setfsuid32 +- case TARGET_NR_setfsuid32: +- ret = get_errno(setfsuid(arg1)); +- break; +-#endif +-#ifdef TARGET_NR_setfsgid32 +- case TARGET_NR_setfsgid32: +- ret = get_errno(setfsgid(arg1)); +- break; +-#endif +- +- case TARGET_NR_pivot_root: +- goto unimplemented; +-#ifdef TARGET_NR_mincore +- case TARGET_NR_mincore: +- { +- void *a; +- ret = -TARGET_EFAULT; +- if (!(a = lock_user(VERIFY_READ, arg1,arg2, 0))) +- goto efault; +- if (!(p = lock_user_string(arg3))) +- goto mincore_fail; +- ret = get_errno(mincore(a, arg2, p)); +- unlock_user(p, arg3, ret); +- mincore_fail: +- unlock_user(a, arg1, 0); +- } +- break; +-#endif +-#ifdef TARGET_NR_arm_fadvise64_64 +- case TARGET_NR_arm_fadvise64_64: +- { +- /* +- * arm_fadvise64_64 looks like fadvise64_64 but +- * with different argument order +- */ +- abi_long temp; +- temp = arg3; +- arg3 = arg4; +- arg4 = temp; +- } +-#endif +-#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_arm_fadvise64_64) || defined(TARGET_NR_fadvise64) +-#ifdef TARGET_NR_fadvise64_64 +- case TARGET_NR_fadvise64_64: +-#endif +-#ifdef TARGET_NR_fadvise64 +- case TARGET_NR_fadvise64: +-#endif +-#ifdef TARGET_S390X +- switch (arg4) { +- case 4: arg4 = POSIX_FADV_NOREUSE + 1; break; /* make sure it's an invalid value */ +- case 5: arg4 = POSIX_FADV_NOREUSE + 2; break; /* ditto */ +- case 6: arg4 = POSIX_FADV_DONTNEED; break; +- case 7: arg4 = POSIX_FADV_NOREUSE; break; +- default: break; +- } +-#endif +- ret = -posix_fadvise(arg1, arg2, arg3, arg4); +- break; +-#endif +-#ifdef TARGET_NR_madvise +- case TARGET_NR_madvise: +- /* A straight passthrough may not be safe because qemu sometimes +- turns private file-backed mappings into anonymous mappings. +- This will break MADV_DONTNEED. +- This is a hint, so ignoring and returning success is ok. */ +- ret = get_errno(0); +- break; +-#endif +-#if TARGET_ABI_BITS == 32 +- case TARGET_NR_fcntl64: +- { +- int cmd; +- struct flock64 fl; +- struct target_flock64 *target_fl; +-#ifdef TARGET_ARM +- struct target_eabi_flock64 *target_efl; +-#endif +- +- cmd = target_to_host_fcntl_cmd(arg2); +- if (cmd == -TARGET_EINVAL) { +- ret = cmd; +- break; +- } +- +- switch(arg2) { +- case TARGET_F_GETLK64: +-#ifdef TARGET_ARM +- if (((CPUARMState *)cpu_env)->eabi) { +- if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1)) +- goto efault; +- fl.l_type = tswap16(target_efl->l_type); +- fl.l_whence = tswap16(target_efl->l_whence); +- fl.l_start = tswap64(target_efl->l_start); +- fl.l_len = tswap64(target_efl->l_len); +- fl.l_pid = tswap32(target_efl->l_pid); +- unlock_user_struct(target_efl, arg3, 0); +- } else +-#endif +- { +- if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1)) +- goto efault; +- fl.l_type = tswap16(target_fl->l_type); +- fl.l_whence = tswap16(target_fl->l_whence); +- fl.l_start = tswap64(target_fl->l_start); +- fl.l_len = tswap64(target_fl->l_len); +- fl.l_pid = tswap32(target_fl->l_pid); +- unlock_user_struct(target_fl, arg3, 0); +- } +- ret = get_errno(fcntl(arg1, cmd, &fl)); +- if (ret == 0) { +-#ifdef TARGET_ARM +- if (((CPUARMState *)cpu_env)->eabi) { +- if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0)) +- goto efault; +- target_efl->l_type = tswap16(fl.l_type); +- target_efl->l_whence = tswap16(fl.l_whence); +- target_efl->l_start = tswap64(fl.l_start); +- target_efl->l_len = tswap64(fl.l_len); +- target_efl->l_pid = tswap32(fl.l_pid); +- unlock_user_struct(target_efl, arg3, 1); +- } else +-#endif +- { +- if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0)) +- goto efault; +- target_fl->l_type = tswap16(fl.l_type); +- target_fl->l_whence = tswap16(fl.l_whence); +- target_fl->l_start = tswap64(fl.l_start); +- target_fl->l_len = tswap64(fl.l_len); +- target_fl->l_pid = tswap32(fl.l_pid); +- unlock_user_struct(target_fl, arg3, 1); +- } +- } +- break; +- +- case TARGET_F_SETLK64: +- case TARGET_F_SETLKW64: +-#ifdef TARGET_ARM +- if (((CPUARMState *)cpu_env)->eabi) { +- if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1)) +- goto efault; +- fl.l_type = tswap16(target_efl->l_type); +- fl.l_whence = tswap16(target_efl->l_whence); +- fl.l_start = tswap64(target_efl->l_start); +- fl.l_len = tswap64(target_efl->l_len); +- fl.l_pid = tswap32(target_efl->l_pid); +- unlock_user_struct(target_efl, arg3, 0); +- } else +-#endif +- { +- if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1)) +- goto efault; +- fl.l_type = tswap16(target_fl->l_type); +- fl.l_whence = tswap16(target_fl->l_whence); +- fl.l_start = tswap64(target_fl->l_start); +- fl.l_len = tswap64(target_fl->l_len); +- fl.l_pid = tswap32(target_fl->l_pid); +- unlock_user_struct(target_fl, arg3, 0); +- } +- ret = get_errno(fcntl(arg1, cmd, &fl)); +- break; +- default: +- ret = do_fcntl(arg1, arg2, arg3); +- break; +- } +- break; +- } +-#endif +-#ifdef TARGET_NR_cacheflush +- case TARGET_NR_cacheflush: +- /* self-modifying code is handled automatically, so nothing needed */ +- ret = 0; +- break; +-#endif +-#ifdef TARGET_NR_security +- case TARGET_NR_security: +- goto unimplemented; +-#endif +-#ifdef TARGET_NR_getpagesize +- case TARGET_NR_getpagesize: +- ret = TARGET_PAGE_SIZE; +- break; +-#endif +- case TARGET_NR_gettid: +- ret = get_errno(gettid()); +- break; +-#ifdef TARGET_NR_readahead +- case TARGET_NR_readahead: +-#if TARGET_ABI_BITS == 32 +- if (regpairs_aligned(cpu_env)) { +- arg2 = arg3; +- arg3 = arg4; +- arg4 = arg5; +- } +- ret = get_errno(readahead(arg1, ((off64_t)arg3 << 32) | arg2, arg4)); +-#else +- ret = get_errno(readahead(arg1, arg2, arg3)); +-#endif +- break; +-#endif +-#ifdef CONFIG_ATTR +-#ifdef TARGET_NR_setxattr +- case TARGET_NR_listxattr: +- case TARGET_NR_llistxattr: +- { +- void *p, *b = 0; +- if (arg2) { +- b = lock_user(VERIFY_WRITE, arg2, arg3, 0); +- if (!b) { +- ret = -TARGET_EFAULT; +- break; +- } +- } +- p = lock_user_string(arg1); +- if (p) { +- if (num == TARGET_NR_listxattr) { +- ret = get_errno(listxattr(p, b, arg3)); +- } else { +- ret = get_errno(llistxattr(p, b, arg3)); +- } +- } else { +- ret = -TARGET_EFAULT; +- } +- unlock_user(p, arg1, 0); +- unlock_user(b, arg2, arg3); +- break; +- } +- case TARGET_NR_flistxattr: +- { +- void *b = 0; +- if (arg2) { +- b = lock_user(VERIFY_WRITE, arg2, arg3, 0); +- if (!b) { +- ret = -TARGET_EFAULT; +- break; +- } +- } +- ret = get_errno(flistxattr(arg1, b, arg3)); +- unlock_user(b, arg2, arg3); +- break; +- } +- case TARGET_NR_setxattr: +- case TARGET_NR_lsetxattr: +- { +- void *p, *n, *v = 0; +- if (arg3) { +- v = lock_user(VERIFY_READ, arg3, arg4, 1); +- if (!v) { +- ret = -TARGET_EFAULT; +- break; +- } +- } +- p = lock_user_string(arg1); +- n = lock_user_string(arg2); +- if (p && n) { +- if (num == TARGET_NR_setxattr) { +- ret = get_errno(setxattr(p, n, v, arg4, arg5)); +- } else { +- ret = get_errno(lsetxattr(p, n, v, arg4, arg5)); +- } +- } else { +- ret = -TARGET_EFAULT; +- } +- unlock_user(p, arg1, 0); +- unlock_user(n, arg2, 0); +- unlock_user(v, arg3, 0); +- } +- break; +- case TARGET_NR_fsetxattr: +- { +- void *n, *v = 0; +- if (arg3) { +- v = lock_user(VERIFY_READ, arg3, arg4, 1); +- if (!v) { +- ret = -TARGET_EFAULT; +- break; +- } +- } +- n = lock_user_string(arg2); +- if (n) { +- ret = get_errno(fsetxattr(arg1, n, v, arg4, arg5)); +- } else { +- ret = -TARGET_EFAULT; +- } +- unlock_user(n, arg2, 0); +- unlock_user(v, arg3, 0); +- } +- break; +- case TARGET_NR_getxattr: +- case TARGET_NR_lgetxattr: +- { +- void *p, *n, *v = 0; +- if (arg3) { +- v = lock_user(VERIFY_WRITE, arg3, arg4, 0); +- if (!v) { +- ret = -TARGET_EFAULT; +- break; +- } +- } +- p = lock_user_string(arg1); +- n = lock_user_string(arg2); +- if (p && n) { +- if (num == TARGET_NR_getxattr) { +- ret = get_errno(getxattr(p, n, v, arg4)); +- } else { +- ret = get_errno(lgetxattr(p, n, v, arg4)); +- } +- } else { +- ret = -TARGET_EFAULT; +- } +- unlock_user(p, arg1, 0); +- unlock_user(n, arg2, 0); +- unlock_user(v, arg3, arg4); +- } +- break; +- case TARGET_NR_fgetxattr: +- { +- void *n, *v = 0; +- if (arg3) { +- v = lock_user(VERIFY_WRITE, arg3, arg4, 0); +- if (!v) { +- ret = -TARGET_EFAULT; +- break; +- } +- } +- n = lock_user_string(arg2); +- if (n) { +- ret = get_errno(fgetxattr(arg1, n, v, arg4)); +- } else { +- ret = -TARGET_EFAULT; +- } +- unlock_user(n, arg2, 0); +- unlock_user(v, arg3, arg4); +- } +- break; +- case TARGET_NR_removexattr: +- case TARGET_NR_lremovexattr: +- { +- void *p, *n; +- p = lock_user_string(arg1); +- n = lock_user_string(arg2); +- if (p && n) { +- if (num == TARGET_NR_removexattr) { +- ret = get_errno(removexattr(p, n)); +- } else { +- ret = get_errno(lremovexattr(p, n)); +- } +- } else { +- ret = -TARGET_EFAULT; +- } +- unlock_user(p, arg1, 0); +- unlock_user(n, arg2, 0); +- } +- break; +- case TARGET_NR_fremovexattr: +- { +- void *n; +- n = lock_user_string(arg2); +- if (n) { +- ret = get_errno(fremovexattr(arg1, n)); +- } else { +- ret = -TARGET_EFAULT; +- } +- unlock_user(n, arg2, 0); +- } +- break; +-#endif +-#endif /* CONFIG_ATTR */ +-#ifdef TARGET_NR_set_thread_area +- case TARGET_NR_set_thread_area: +-#if defined(TARGET_MIPS) +- ((CPUMIPSState *) cpu_env)->active_tc.CP0_UserLocal = arg1; +- ret = 0; +- break; +-#elif defined(TARGET_CRIS) +- if (arg1 & 0xff) +- ret = -TARGET_EINVAL; +- else { +- ((CPUCRISState *) cpu_env)->pregs[PR_PID] = arg1; +- ret = 0; +- } +- break; +-#elif defined(TARGET_I386) && defined(TARGET_ABI32) +- ret = do_set_thread_area(cpu_env, arg1); +- break; +-#elif defined(TARGET_M68K) +- { +- TaskState *ts = cpu->opaque; +- ts->tp_value = arg1; +- ret = 0; +- break; +- } +-#else +- goto unimplemented_nowarn; +-#endif +-#endif +-#ifdef TARGET_NR_get_thread_area +- case TARGET_NR_get_thread_area: +-#if defined(TARGET_I386) && defined(TARGET_ABI32) +- ret = do_get_thread_area(cpu_env, arg1); +- break; +-#elif defined(TARGET_M68K) +- { +- TaskState *ts = cpu->opaque; +- ret = ts->tp_value; +- break; +- } +-#else +- goto unimplemented_nowarn; +-#endif +-#endif +-#ifdef TARGET_NR_getdomainname +- case TARGET_NR_getdomainname: +- goto unimplemented_nowarn; +-#endif +- +-#ifdef TARGET_NR_clock_gettime +- case TARGET_NR_clock_gettime: +- { +- struct timespec ts; +- ret = get_errno(clock_gettime(arg1, &ts)); +- if (!is_error(ret)) { +- host_to_target_timespec(arg2, &ts); +- } +- break; +- } +-#endif +-#ifdef TARGET_NR_clock_getres +- case TARGET_NR_clock_getres: +- { +- struct timespec ts; +- ret = get_errno(clock_getres(arg1, &ts)); +- if (!is_error(ret)) { +- host_to_target_timespec(arg2, &ts); +- } +- break; +- } +-#endif +-#ifdef TARGET_NR_clock_nanosleep +- case TARGET_NR_clock_nanosleep: +- { +- struct timespec ts; +- target_to_host_timespec(&ts, arg3); +- ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL)); +- if (arg4) +- host_to_target_timespec(arg4, &ts); +- +-#if defined(TARGET_PPC) +- /* clock_nanosleep is odd in that it returns positive errno values. +- * On PPC, CR0 bit 3 should be set in such a situation. */ +- if (ret) { +- ((CPUPPCState *)cpu_env)->crf[0] |= 1; +- } +-#endif +- break; +- } +-#endif +- +-#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address) +- case TARGET_NR_set_tid_address: +- ret = get_errno(set_tid_address((int *)g2h(arg1))); +- break; +-#endif +- +-#if defined(TARGET_NR_tkill) && defined(__NR_tkill) +- case TARGET_NR_tkill: +- ret = get_errno(sys_tkill((int)arg1, target_to_host_signal(arg2))); +- break; +-#endif +- +-#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill) +- case TARGET_NR_tgkill: +- ret = get_errno(sys_tgkill((int)arg1, (int)arg2, +- target_to_host_signal(arg3))); +- break; +-#endif +- +-#ifdef TARGET_NR_set_robust_list +- case TARGET_NR_set_robust_list: +- case TARGET_NR_get_robust_list: +- /* The ABI for supporting robust futexes has userspace pass +- * the kernel a pointer to a linked list which is updated by +- * userspace after the syscall; the list is walked by the kernel +- * when the thread exits. Since the linked list in QEMU guest +- * memory isn't a valid linked list for the host and we have +- * no way to reliably intercept the thread-death event, we can't +- * support these. Silently return ENOSYS so that guest userspace +- * falls back to a non-robust futex implementation (which should +- * be OK except in the corner case of the guest crashing while +- * holding a mutex that is shared with another process via +- * shared memory). +- */ +- goto unimplemented_nowarn; +-#endif +- +-#if defined(TARGET_NR_utimensat) +- case TARGET_NR_utimensat: +- { +- struct timespec *tsp, ts[2]; +- if (!arg3) { +- tsp = NULL; +- } else { +- target_to_host_timespec(ts, arg3); +- target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec)); +- tsp = ts; +- } +- if (!arg2) +- ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4)); +- else { +- if (!(p = lock_user_string(arg2))) { +- ret = -TARGET_EFAULT; +- goto fail; +- } +- ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4)); +- unlock_user(p, arg2, 0); +- } +- } +- break; +-#endif +- case TARGET_NR_futex: +- ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6); +- break; +-#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init) +- case TARGET_NR_inotify_init: +- ret = get_errno(sys_inotify_init()); +- break; +-#endif +-#ifdef CONFIG_INOTIFY1 +-#if defined(TARGET_NR_inotify_init1) && defined(__NR_inotify_init1) +- case TARGET_NR_inotify_init1: +- ret = get_errno(sys_inotify_init1(arg1)); +- break; +-#endif +-#endif +-#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch) +- case TARGET_NR_inotify_add_watch: +- p = lock_user_string(arg2); +- ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3)); +- unlock_user(p, arg2, 0); +- break; +-#endif +-#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch) +- case TARGET_NR_inotify_rm_watch: +- ret = get_errno(sys_inotify_rm_watch(arg1, arg2)); +- break; +-#endif +- +-#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open) +- case TARGET_NR_mq_open: +- { +- struct mq_attr posix_mq_attr, *attrp; +- +- p = lock_user_string(arg1 - 1); +- if (arg4 != 0) { +- copy_from_user_mq_attr (&posix_mq_attr, arg4); +- attrp = &posix_mq_attr; +- } else { +- attrp = 0; +- } +- ret = get_errno(mq_open(p, arg2, arg3, attrp)); +- unlock_user (p, arg1, 0); +- } +- break; +- +- case TARGET_NR_mq_unlink: +- p = lock_user_string(arg1 - 1); +- ret = get_errno(mq_unlink(p)); +- unlock_user (p, arg1, 0); +- break; +- +- case TARGET_NR_mq_timedsend: +- { +- struct timespec ts; +- +- p = lock_user (VERIFY_READ, arg2, arg3, 1); +- if (arg5 != 0) { +- target_to_host_timespec(&ts, arg5); +- ret = get_errno(mq_timedsend(arg1, p, arg3, arg4, &ts)); +- host_to_target_timespec(arg5, &ts); +- } +- else +- ret = get_errno(mq_send(arg1, p, arg3, arg4)); +- unlock_user (p, arg2, arg3); +- } +- break; +- +- case TARGET_NR_mq_timedreceive: +- { +- struct timespec ts; +- unsigned int prio; +- +- p = lock_user (VERIFY_READ, arg2, arg3, 1); +- if (arg5 != 0) { +- target_to_host_timespec(&ts, arg5); +- ret = get_errno(mq_timedreceive(arg1, p, arg3, &prio, &ts)); +- host_to_target_timespec(arg5, &ts); +- } +- else +- ret = get_errno(mq_receive(arg1, p, arg3, &prio)); +- unlock_user (p, arg2, arg3); +- if (arg4 != 0) +- put_user_u32(prio, arg4); +- } +- break; +- +- /* Not implemented for now... */ +-/* case TARGET_NR_mq_notify: */ +-/* break; */ +- +- case TARGET_NR_mq_getsetattr: +- { +- struct mq_attr posix_mq_attr_in, posix_mq_attr_out; +- ret = 0; +- if (arg3 != 0) { +- ret = mq_getattr(arg1, &posix_mq_attr_out); +- copy_to_user_mq_attr(arg3, &posix_mq_attr_out); +- } +- if (arg2 != 0) { +- copy_from_user_mq_attr(&posix_mq_attr_in, arg2); +- ret |= mq_setattr(arg1, &posix_mq_attr_in, &posix_mq_attr_out); +- } +- +- } +- break; +-#endif +- +-#ifdef CONFIG_SPLICE +-#ifdef TARGET_NR_tee +- case TARGET_NR_tee: +- { +- ret = get_errno(tee(arg1,arg2,arg3,arg4)); +- } +- break; +-#endif +-#ifdef TARGET_NR_splice +- case TARGET_NR_splice: +- { +- loff_t loff_in, loff_out; +- loff_t *ploff_in = NULL, *ploff_out = NULL; +- if (arg2) { +- if (get_user_u64(loff_in, arg2)) { +- goto efault; +- } +- ploff_in = &loff_in; +- } +- if (arg4) { +- if (get_user_u64(loff_out, arg4)) { +- goto efault; +- } +- ploff_out = &loff_out; +- } +- ret = get_errno(splice(arg1, ploff_in, arg3, ploff_out, arg5, arg6)); +- if (arg2) { +- if (put_user_u64(loff_in, arg2)) { +- goto efault; +- } +- } +- if (arg4) { +- if (put_user_u64(loff_out, arg4)) { +- goto efault; +- } +- } +- } +- break; +-#endif +-#ifdef TARGET_NR_vmsplice +- case TARGET_NR_vmsplice: +- { +- struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1); +- if (vec != NULL) { +- ret = get_errno(vmsplice(arg1, vec, arg3, arg4)); +- unlock_iovec(vec, arg2, arg3, 0); +- } else { +- ret = -host_to_target_errno(errno); +- } +- } +- break; +-#endif +-#endif /* CONFIG_SPLICE */ +-#ifdef CONFIG_EVENTFD +-#if defined(TARGET_NR_eventfd) +- case TARGET_NR_eventfd: +- ret = get_errno(eventfd(arg1, 0)); +- break; +-#endif +-#if defined(TARGET_NR_eventfd2) +- case TARGET_NR_eventfd2: +- { +- int host_flags = arg2 & (~(TARGET_O_NONBLOCK | TARGET_O_CLOEXEC)); +- if (arg2 & TARGET_O_NONBLOCK) { +- host_flags |= O_NONBLOCK; +- } +- if (arg2 & TARGET_O_CLOEXEC) { +- host_flags |= O_CLOEXEC; +- } +- ret = get_errno(eventfd(arg1, host_flags)); +- break; +- } +-#endif +-#endif /* CONFIG_EVENTFD */ +-#if defined(CONFIG_FALLOCATE) && defined(TARGET_NR_fallocate) +- case TARGET_NR_fallocate: +-#if TARGET_ABI_BITS == 32 +- ret = get_errno(fallocate(arg1, arg2, target_offset64(arg3, arg4), +- target_offset64(arg5, arg6))); +-#else +- ret = get_errno(fallocate(arg1, arg2, arg3, arg4)); +-#endif +- break; +-#endif +-#if defined(CONFIG_SYNC_FILE_RANGE) +-#if defined(TARGET_NR_sync_file_range) +- case TARGET_NR_sync_file_range: +-#if TARGET_ABI_BITS == 32 +-#if defined(TARGET_MIPS) +- ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4), +- target_offset64(arg5, arg6), arg7)); +-#else +- ret = get_errno(sync_file_range(arg1, target_offset64(arg2, arg3), +- target_offset64(arg4, arg5), arg6)); +-#endif /* !TARGET_MIPS */ +-#else +- ret = get_errno(sync_file_range(arg1, arg2, arg3, arg4)); +-#endif +- break; +-#endif +-#if defined(TARGET_NR_sync_file_range2) +- case TARGET_NR_sync_file_range2: +- /* This is like sync_file_range but the arguments are reordered */ +-#if TARGET_ABI_BITS == 32 +- ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4), +- target_offset64(arg5, arg6), arg2)); +-#else +- ret = get_errno(sync_file_range(arg1, arg3, arg4, arg2)); +-#endif +- break; +-#endif +-#endif +-#if defined(CONFIG_EPOLL) +-#if defined(TARGET_NR_epoll_create) +- case TARGET_NR_epoll_create: +- ret = get_errno(epoll_create(arg1)); +- break; +-#endif +-#if defined(TARGET_NR_epoll_create1) && defined(CONFIG_EPOLL_CREATE1) +- case TARGET_NR_epoll_create1: +- ret = get_errno(epoll_create1(arg1)); +- break; +-#endif +-#if defined(TARGET_NR_epoll_ctl) +- case TARGET_NR_epoll_ctl: +- { +- struct epoll_event ep; +- struct epoll_event *epp = 0; +- if (arg4) { +- struct target_epoll_event *target_ep; +- if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) { +- goto efault; +- } +- ep.events = tswap32(target_ep->events); +- /* The epoll_data_t union is just opaque data to the kernel, +- * so we transfer all 64 bits across and need not worry what +- * actual data type it is. +- */ +- ep.data.u64 = tswap64(target_ep->data.u64); +- unlock_user_struct(target_ep, arg4, 0); +- epp = &ep; +- } +- ret = get_errno(epoll_ctl(arg1, arg2, arg3, epp)); +- break; +- } +-#endif +- +-#if defined(TARGET_NR_epoll_pwait) && defined(CONFIG_EPOLL_PWAIT) +-#define IMPLEMENT_EPOLL_PWAIT +-#endif +-#if defined(TARGET_NR_epoll_wait) || defined(IMPLEMENT_EPOLL_PWAIT) +-#if defined(TARGET_NR_epoll_wait) +- case TARGET_NR_epoll_wait: +-#endif +-#if defined(IMPLEMENT_EPOLL_PWAIT) +- case TARGET_NR_epoll_pwait: +-#endif +- { +- struct target_epoll_event *target_ep; +- struct epoll_event *ep; +- int epfd = arg1; +- int maxevents = arg3; +- int timeout = arg4; +- +- target_ep = lock_user(VERIFY_WRITE, arg2, +- maxevents * sizeof(struct target_epoll_event), 1); +- if (!target_ep) { +- goto efault; +- } +- +- ep = alloca(maxevents * sizeof(struct epoll_event)); +- +- switch (num) { +-#if defined(IMPLEMENT_EPOLL_PWAIT) +- case TARGET_NR_epoll_pwait: +- { +- target_sigset_t *target_set; +- sigset_t _set, *set = &_set; +- +- if (arg5) { +- target_set = lock_user(VERIFY_READ, arg5, +- sizeof(target_sigset_t), 1); +- if (!target_set) { +- unlock_user(target_ep, arg2, 0); +- goto efault; +- } +- target_to_host_sigset(set, target_set); +- unlock_user(target_set, arg5, 0); +- } else { +- set = NULL; +- } +- +- ret = get_errno(epoll_pwait(epfd, ep, maxevents, timeout, set)); +- break; +- } +-#endif +-#if defined(TARGET_NR_epoll_wait) +- case TARGET_NR_epoll_wait: +- ret = get_errno(epoll_wait(epfd, ep, maxevents, timeout)); +- break; +-#endif +- default: +- ret = -TARGET_ENOSYS; +- } +- if (!is_error(ret)) { +- int i; +- for (i = 0; i < ret; i++) { +- target_ep[i].events = tswap32(ep[i].events); +- target_ep[i].data.u64 = tswap64(ep[i].data.u64); +- } +- } +- unlock_user(target_ep, arg2, ret * sizeof(struct target_epoll_event)); +- break; +- } +-#endif +-#endif +-#ifdef TARGET_NR_prlimit64 +- case TARGET_NR_prlimit64: +- { +- /* args: pid, resource number, ptr to new rlimit, ptr to old rlimit */ +- struct target_rlimit64 *target_rnew, *target_rold; +- struct host_rlimit64 rnew, rold, *rnewp = 0; +- int resource = target_to_host_resource(arg2); +- if (arg3) { +- if (!lock_user_struct(VERIFY_READ, target_rnew, arg3, 1)) { +- goto efault; +- } +- rnew.rlim_cur = tswap64(target_rnew->rlim_cur); +- rnew.rlim_max = tswap64(target_rnew->rlim_max); +- unlock_user_struct(target_rnew, arg3, 0); +- rnewp = &rnew; +- } +- +- ret = get_errno(sys_prlimit64(arg1, resource, rnewp, arg4 ? &rold : 0)); +- if (!is_error(ret) && arg4) { +- if (!lock_user_struct(VERIFY_WRITE, target_rold, arg4, 1)) { +- goto efault; +- } +- target_rold->rlim_cur = tswap64(rold.rlim_cur); +- target_rold->rlim_max = tswap64(rold.rlim_max); +- unlock_user_struct(target_rold, arg4, 1); +- } +- break; +- } +-#endif +-#ifdef TARGET_NR_gethostname +- case TARGET_NR_gethostname: +- { +- char *name = lock_user(VERIFY_WRITE, arg1, arg2, 0); +- if (name) { +- ret = get_errno(gethostname(name, arg2)); +- unlock_user(name, arg1, arg2); +- } else { +- ret = -TARGET_EFAULT; +- } +- break; +- } +-#endif +-#ifdef TARGET_NR_atomic_cmpxchg_32 +- case TARGET_NR_atomic_cmpxchg_32: +- { +- /* should use start_exclusive from main.c */ +- abi_ulong mem_value; +- if (get_user_u32(mem_value, arg6)) { +- target_siginfo_t info; +- info.si_signo = SIGSEGV; +- info.si_errno = 0; +- info.si_code = TARGET_SEGV_MAPERR; +- info._sifields._sigfault._addr = arg6; +- queue_signal((CPUArchState *)cpu_env, info.si_signo, &info); +- ret = 0xdeadbeef; +- +- } +- if (mem_value == arg2) +- put_user_u32(arg1, arg6); +- ret = mem_value; +- break; +- } +-#endif +-#ifdef TARGET_NR_atomic_barrier +- case TARGET_NR_atomic_barrier: +- { +- /* Like the kernel implementation and the qemu arm barrier, no-op this? */ +- ret = 0; +- break; +- } +-#endif +- +-#ifdef TARGET_NR_timer_create +- case TARGET_NR_timer_create: +- { +- /* args: clockid_t clockid, struct sigevent *sevp, timer_t *timerid */ +- +- struct sigevent host_sevp = { {0}, }, *phost_sevp = NULL; +- +- int clkid = arg1; +- int timer_index = next_free_host_timer(); +- +- if (timer_index < 0) { +- ret = -TARGET_EAGAIN; +- } else { +- timer_t *phtimer = g_posix_timers + timer_index; +- +- if (arg2) { +- phost_sevp = &host_sevp; +- ret = target_to_host_sigevent(phost_sevp, arg2); +- if (ret != 0) { +- break; +- } +- } +- +- ret = get_errno(timer_create(clkid, phost_sevp, phtimer)); +- if (ret) { +- phtimer = NULL; +- } else { +- if (put_user(TIMER_MAGIC | timer_index, arg3, target_timer_t)) { +- goto efault; +- } +- } +- } +- break; +- } +-#endif +- +-#ifdef TARGET_NR_timer_settime +- case TARGET_NR_timer_settime: +- { +- /* args: timer_t timerid, int flags, const struct itimerspec *new_value, +- * struct itimerspec * old_value */ +- target_timer_t timerid = get_timer_id(arg1); +- +- if (timerid < 0) { +- ret = timerid; +- } else if (arg3 == 0) { +- ret = -TARGET_EINVAL; +- } else { +- timer_t htimer = g_posix_timers[timerid]; +- struct itimerspec hspec_new = {{0},}, hspec_old = {{0},}; +- +- target_to_host_itimerspec(&hspec_new, arg3); +- ret = get_errno( +- timer_settime(htimer, arg2, &hspec_new, &hspec_old)); +- host_to_target_itimerspec(arg2, &hspec_old); +- } +- break; +- } +-#endif +- +-#ifdef TARGET_NR_timer_gettime +- case TARGET_NR_timer_gettime: +- { +- /* args: timer_t timerid, struct itimerspec *curr_value */ +- target_timer_t timerid = get_timer_id(arg1); +- +- if (timerid < 0) { +- ret = timerid; +- } else if (!arg2) { +- ret = -TARGET_EFAULT; +- } else { +- timer_t htimer = g_posix_timers[timerid]; +- struct itimerspec hspec; +- ret = get_errno(timer_gettime(htimer, &hspec)); +- +- if (host_to_target_itimerspec(arg2, &hspec)) { +- ret = -TARGET_EFAULT; +- } +- } +- break; +- } +-#endif +- +-#ifdef TARGET_NR_timer_getoverrun +- case TARGET_NR_timer_getoverrun: +- { +- /* args: timer_t timerid */ +- target_timer_t timerid = get_timer_id(arg1); +- +- if (timerid < 0) { +- ret = timerid; +- } else { +- timer_t htimer = g_posix_timers[timerid]; +- ret = get_errno(timer_getoverrun(htimer)); +- } +- break; +- } +-#endif +- +-#ifdef TARGET_NR_timer_delete +- case TARGET_NR_timer_delete: +- { +- /* args: timer_t timerid */ +- target_timer_t timerid = get_timer_id(arg1); +- +- if (timerid < 0) { +- ret = timerid; +- } else { +- timer_t htimer = g_posix_timers[timerid]; +- ret = get_errno(timer_delete(htimer)); +- g_posix_timers[timerid] = 0; +- } +- break; +- } +-#endif +- +-#if defined(TARGET_NR_timerfd_create) && defined(CONFIG_TIMERFD) +- case TARGET_NR_timerfd_create: +- ret = get_errno(timerfd_create(arg1, +- target_to_host_bitmask(arg2, fcntl_flags_tbl))); +- break; +-#endif +- +-#if defined(TARGET_NR_timerfd_gettime) && defined(CONFIG_TIMERFD) +- case TARGET_NR_timerfd_gettime: +- { +- struct itimerspec its_curr; +- +- ret = get_errno(timerfd_gettime(arg1, &its_curr)); +- +- if (arg2 && host_to_target_itimerspec(arg2, &its_curr)) { +- goto efault; +- } +- } +- break; +-#endif +- +-#if defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD) +- case TARGET_NR_timerfd_settime: +- { +- struct itimerspec its_new, its_old, *p_new; +- +- if (arg3) { +- if (target_to_host_itimerspec(&its_new, arg3)) { +- goto efault; +- } +- p_new = &its_new; +- } else { +- p_new = NULL; +- } +- +- ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old)); +- +- if (arg4 && host_to_target_itimerspec(arg4, &its_old)) { +- goto efault; +- } +- } +- break; +-#endif +- +-#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get) +- case TARGET_NR_ioprio_get: +- ret = get_errno(ioprio_get(arg1, arg2)); +- break; +-#endif +- +-#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set) +- case TARGET_NR_ioprio_set: +- ret = get_errno(ioprio_set(arg1, arg2, arg3)); +- break; +-#endif +- +-#if defined(TARGET_NR_setns) && defined(CONFIG_SETNS) +- case TARGET_NR_setns: +- ret = get_errno(setns(arg1, arg2)); +- break; +-#endif +-#if defined(TARGET_NR_unshare) && defined(CONFIG_SETNS) +- case TARGET_NR_unshare: +- ret = get_errno(unshare(arg1)); +- break; +-#endif +- +- default: +- unimplemented: +- gemu_log("qemu: Unsupported syscall: %d\n", num); +-#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_get_thread_area) || defined(TARGET_NR_getdomainname) || defined(TARGET_NR_set_robust_list) +- unimplemented_nowarn: +-#endif +- ret = -TARGET_ENOSYS; +- break; +- } +-fail: +-#ifdef DEBUG +- gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret); +-#endif +- if(do_strace) +- print_syscall_ret(num, ret); +- return ret; +-efault: +- ret = -TARGET_EFAULT; +- goto fail; +-} +diff --git a/home/gkrishna/Shelly/work/qemu/linux-user/syscall_defs.h b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/syscall_defs.h +index edd5f3c..29f21ae 100644 +--- a/home/gkrishna/Shelly/work/qemu/linux-user/syscall_defs.h ++++ b/home/gkrishna/Shelly/work/qemu-cgc/linux-user/syscall_defs.h +@@ -10,306 +10,14 @@ + + #include "syscall_nr.h" + +-#define SOCKOP_socket 1 +-#define SOCKOP_bind 2 +-#define SOCKOP_connect 3 +-#define SOCKOP_listen 4 +-#define SOCKOP_accept 5 +-#define SOCKOP_getsockname 6 +-#define SOCKOP_getpeername 7 +-#define SOCKOP_socketpair 8 +-#define SOCKOP_send 9 +-#define SOCKOP_recv 10 +-#define SOCKOP_sendto 11 +-#define SOCKOP_recvfrom 12 +-#define SOCKOP_shutdown 13 +-#define SOCKOP_setsockopt 14 +-#define SOCKOP_getsockopt 15 +-#define SOCKOP_sendmsg 16 +-#define SOCKOP_recvmsg 17 +-#define SOCKOP_accept4 18 +- +-#define IPCOP_semop 1 +-#define IPCOP_semget 2 +-#define IPCOP_semctl 3 +-#define IPCOP_semtimedop 4 +-#define IPCOP_msgsnd 11 +-#define IPCOP_msgrcv 12 +-#define IPCOP_msgget 13 +-#define IPCOP_msgctl 14 +-#define IPCOP_shmat 21 +-#define IPCOP_shmdt 22 +-#define IPCOP_shmget 23 +-#define IPCOP_shmctl 24 +- +-/* +- * The following is for compatibility across the various Linux +- * platforms. The i386 ioctl numbering scheme doesn't really enforce +- * a type field. De facto, however, the top 8 bits of the lower 16 +- * bits are indeed used as a type field, so we might just as well make +- * this explicit here. Please be sure to use the decoding macros +- * below from now on. +- */ +-#define TARGET_IOC_NRBITS 8 +-#define TARGET_IOC_TYPEBITS 8 +- +-#if defined(TARGET_I386) || (defined(TARGET_ARM) && defined(TARGET_ABI32)) \ +- || defined(TARGET_SPARC) \ +- || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS) +- /* 16 bit uid wrappers emulation */ +-#define USE_UID16 +-#define target_id uint16_t +-#else +-#define target_id uint32_t +-#endif +- +-#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SH4) \ +- || defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_UNICORE32) \ +- || defined(TARGET_S390X) || defined(TARGET_OPENRISC) +- +-#define TARGET_IOC_SIZEBITS 14 +-#define TARGET_IOC_DIRBITS 2 +- +-#define TARGET_IOC_NONE 0U +-#define TARGET_IOC_WRITE 1U +-#define TARGET_IOC_READ 2U +- +-#elif defined(TARGET_PPC) || defined(TARGET_ALPHA) || \ +- defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE) || \ +- defined(TARGET_MIPS) +- +-#define TARGET_IOC_SIZEBITS 13 +-#define TARGET_IOC_DIRBITS 3 +- +-#define TARGET_IOC_NONE 1U +-#define TARGET_IOC_READ 2U +-#define TARGET_IOC_WRITE 4U +- +-#else +-#error unsupported CPU +-#endif +- +-#define TARGET_IOC_NRMASK ((1 << TARGET_IOC_NRBITS)-1) +-#define TARGET_IOC_TYPEMASK ((1 << TARGET_IOC_TYPEBITS)-1) +-#define TARGET_IOC_SIZEMASK ((1 << TARGET_IOC_SIZEBITS)-1) +-#define TARGET_IOC_DIRMASK ((1 << TARGET_IOC_DIRBITS)-1) +- +-#define TARGET_IOC_NRSHIFT 0 +-#define TARGET_IOC_TYPESHIFT (TARGET_IOC_NRSHIFT+TARGET_IOC_NRBITS) +-#define TARGET_IOC_SIZESHIFT (TARGET_IOC_TYPESHIFT+TARGET_IOC_TYPEBITS) +-#define TARGET_IOC_DIRSHIFT (TARGET_IOC_SIZESHIFT+TARGET_IOC_SIZEBITS) +- +-#define TARGET_IOC(dir,type,nr,size) \ +- (((dir) << TARGET_IOC_DIRSHIFT) | \ +- ((type) << TARGET_IOC_TYPESHIFT) | \ +- ((nr) << TARGET_IOC_NRSHIFT) | \ +- ((size) << TARGET_IOC_SIZESHIFT)) +- +-/* used to create numbers */ +-#define TARGET_IO(type,nr) TARGET_IOC(TARGET_IOC_NONE,(type),(nr),0) +-#define TARGET_IOR(type,nr,size) TARGET_IOC(TARGET_IOC_READ,(type),(nr),sizeof(size)) +-#define TARGET_IOW(type,nr,size) TARGET_IOC(TARGET_IOC_WRITE,(type),(nr),sizeof(size)) +-#define TARGET_IOWR(type,nr,size) TARGET_IOC(TARGET_IOC_READ|TARGET_IOC_WRITE,(type),(nr),sizeof(size)) +- +-/* the size is automatically computed for these defines */ +-#define TARGET_IORU(type,nr) TARGET_IOC(TARGET_IOC_READ,(type),(nr),TARGET_IOC_SIZEMASK) +-#define TARGET_IOWU(type,nr) TARGET_IOC(TARGET_IOC_WRITE,(type),(nr),TARGET_IOC_SIZEMASK) +-#define TARGET_IOWRU(type,nr) TARGET_IOC(TARGET_IOC_READ|TARGET_IOC_WRITE,(type),(nr),TARGET_IOC_SIZEMASK) +- +-struct target_sockaddr { +- uint16_t sa_family; +- uint8_t sa_data[14]; +-}; +- +-struct target_sockaddr_ll { +- uint16_t sll_family; /* Always AF_PACKET */ +- uint16_t sll_protocol; /* Physical layer protocol */ +- int sll_ifindex; /* Interface number */ +- uint16_t sll_hatype; /* ARP hardware type */ +- uint8_t sll_pkttype; /* Packet type */ +- uint8_t sll_halen; /* Length of address */ +- uint8_t sll_addr[8]; /* Physical layer address */ +-}; +- +-struct target_sock_filter { +- abi_ushort code; +- uint8_t jt; +- uint8_t jf; +- abi_uint k; +-}; +- +-struct target_sock_fprog { +- abi_ushort len; +- abi_ulong filter; +-}; +- +-struct target_in_addr { +- uint32_t s_addr; /* big endian */ +-}; +- +-struct target_ip_mreq { +- struct target_in_addr imr_multiaddr; +- struct target_in_addr imr_address; +-}; +- +-struct target_ip_mreqn { +- struct target_in_addr imr_multiaddr; +- struct target_in_addr imr_address; +- abi_long imr_ifindex; +-}; +- +-struct target_ip_mreq_source { +- /* big endian */ +- uint32_t imr_multiaddr; +- uint32_t imr_interface; +- uint32_t imr_sourceaddr; +-}; + + struct target_timeval { + abi_long tv_sec; + abi_long tv_usec; + }; + +-struct target_timespec { +- abi_long tv_sec; +- abi_long tv_nsec; +-}; +- +-struct target_timezone { +- abi_int tz_minuteswest; +- abi_int tz_dsttime; +-}; +- +-struct target_itimerval { +- struct target_timeval it_interval; +- struct target_timeval it_value; +-}; +- +-struct target_itimerspec { +- struct target_timespec it_interval; +- struct target_timespec it_value; +-}; +- + typedef abi_long target_clock_t; + +-#define TARGET_HZ 100 +- +-struct target_tms { +- target_clock_t tms_utime; +- target_clock_t tms_stime; +- target_clock_t tms_cutime; +- target_clock_t tms_cstime; +-}; +- +-struct target_utimbuf { +- abi_long actime; +- abi_long modtime; +-}; +- +-struct target_sel_arg_struct { +- abi_long n; +- abi_long inp, outp, exp; +- abi_long tvp; +-}; +- +-struct target_iovec { +- abi_long iov_base; /* Starting address */ +- abi_long iov_len; /* Number of bytes */ +-}; +- +-struct target_msghdr { +- abi_long msg_name; /* Socket name */ +- int msg_namelen; /* Length of name */ +- abi_long msg_iov; /* Data blocks */ +- abi_long msg_iovlen; /* Number of blocks */ +- abi_long msg_control; /* Per protocol magic (eg BSD file descriptor passing) */ +- abi_long msg_controllen; /* Length of cmsg list */ +- unsigned int msg_flags; +-}; +- +-struct target_cmsghdr { +- abi_long cmsg_len; +- int cmsg_level; +- int cmsg_type; +-}; +- +-#define TARGET_CMSG_DATA(cmsg) ((unsigned char *) ((struct target_cmsghdr *) (cmsg) + 1)) +-#define TARGET_CMSG_NXTHDR(mhdr, cmsg) __target_cmsg_nxthdr (mhdr, cmsg) +-#define TARGET_CMSG_ALIGN(len) (((len) + sizeof (abi_long) - 1) \ +- & (size_t) ~(sizeof (abi_long) - 1)) +-#define TARGET_CMSG_SPACE(len) (TARGET_CMSG_ALIGN (len) \ +- + TARGET_CMSG_ALIGN (sizeof (struct target_cmsghdr))) +-#define TARGET_CMSG_LEN(len) (TARGET_CMSG_ALIGN (sizeof (struct target_cmsghdr)) + (len)) +- +-static __inline__ struct target_cmsghdr * +-__target_cmsg_nxthdr (struct target_msghdr *__mhdr, struct target_cmsghdr *__cmsg) +-{ +- struct target_cmsghdr *__ptr; +- +- __ptr = (struct target_cmsghdr *)((unsigned char *) __cmsg +- + TARGET_CMSG_ALIGN (tswapal(__cmsg->cmsg_len))); +- if ((unsigned long)((char *)(__ptr+1) - (char *)(size_t)tswapal(__mhdr->msg_control)) +- > tswapal(__mhdr->msg_controllen)) +- /* No more entries. */ +- return (struct target_cmsghdr *)0; +- return __cmsg; +-} +- +-struct target_mmsghdr { +- struct target_msghdr msg_hdr; /* Message header */ +- unsigned int msg_len; /* Number of bytes transmitted */ +-}; +- +-struct target_rusage { +- struct target_timeval ru_utime; /* user time used */ +- struct target_timeval ru_stime; /* system time used */ +- abi_long ru_maxrss; /* maximum resident set size */ +- abi_long ru_ixrss; /* integral shared memory size */ +- abi_long ru_idrss; /* integral unshared data size */ +- abi_long ru_isrss; /* integral unshared stack size */ +- abi_long ru_minflt; /* page reclaims */ +- abi_long ru_majflt; /* page faults */ +- abi_long ru_nswap; /* swaps */ +- abi_long ru_inblock; /* block input operations */ +- abi_long ru_oublock; /* block output operations */ +- abi_long ru_msgsnd; /* messages sent */ +- abi_long ru_msgrcv; /* messages received */ +- abi_long ru_nsignals; /* signals received */ +- abi_long ru_nvcsw; /* voluntary context switches */ +- abi_long ru_nivcsw; /* involuntary " */ +-}; +- +-typedef struct { +- int val[2]; +-} kernel_fsid_t; +- +-struct kernel_statfs { +- int f_type; +- int f_bsize; +- int f_blocks; +- int f_bfree; +- int f_bavail; +- int f_files; +- int f_ffree; +- kernel_fsid_t f_fsid; +- int f_namelen; +- int f_spare[6]; +-}; +- +-struct target_dirent { +- abi_long d_ino; +- abi_long d_off; +- unsigned short d_reclen; +- char d_name[]; +-}; +- +-struct target_dirent64 { +- uint64_t d_ino; +- int64_t d_off; +- unsigned short d_reclen; +- unsigned char d_type; +- char d_name[256]; +-}; + + + /* mostly generic signal stuff */ +@@ -317,11 +25,7 @@ struct target_dirent64 { + #define TARGET_SIG_IGN ((abi_long)1) /* ignore signal */ + #define TARGET_SIG_ERR ((abi_long)-1) /* error return from signal */ + +-#ifdef TARGET_MIPS +-#define TARGET_NSIG 128 +-#else + #define TARGET_NSIG 64 +-#endif + #define TARGET_NSIG_BPW TARGET_ABI_BITS + #define TARGET_NSIG_WORDS (TARGET_NSIG / TARGET_NSIG_BPW) + +@@ -777,1790 +481,7 @@ typedef struct target_siginfo { + + #endif /* defined(TARGET_I386) || defined(TARGET_ARM) */ + +-struct target_rlimit { +- abi_ulong rlim_cur; +- abi_ulong rlim_max; +-}; +- +-#if defined(TARGET_ALPHA) +-#define TARGET_RLIM_INFINITY 0x7fffffffffffffffull +-#elif defined(TARGET_MIPS) || (defined(TARGET_SPARC) && TARGET_ABI_BITS == 32) +-#define TARGET_RLIM_INFINITY 0x7fffffffUL +-#else +-#define TARGET_RLIM_INFINITY ((abi_ulong)-1) +-#endif +- +-#if defined(TARGET_MIPS) +-#define TARGET_RLIMIT_CPU 0 +-#define TARGET_RLIMIT_FSIZE 1 +-#define TARGET_RLIMIT_DATA 2 +-#define TARGET_RLIMIT_STACK 3 +-#define TARGET_RLIMIT_CORE 4 +-#define TARGET_RLIMIT_RSS 7 +-#define TARGET_RLIMIT_NPROC 8 +-#define TARGET_RLIMIT_NOFILE 5 +-#define TARGET_RLIMIT_MEMLOCK 9 +-#define TARGET_RLIMIT_AS 6 +-#define TARGET_RLIMIT_LOCKS 10 +-#define TARGET_RLIMIT_SIGPENDING 11 +-#define TARGET_RLIMIT_MSGQUEUE 12 +-#define TARGET_RLIMIT_NICE 13 +-#define TARGET_RLIMIT_RTPRIO 14 +-#else +-#define TARGET_RLIMIT_CPU 0 +-#define TARGET_RLIMIT_FSIZE 1 +-#define TARGET_RLIMIT_DATA 2 +-#define TARGET_RLIMIT_STACK 3 +-#define TARGET_RLIMIT_CORE 4 +-#define TARGET_RLIMIT_RSS 5 +-#if defined(TARGET_SPARC) +-#define TARGET_RLIMIT_NOFILE 6 +-#define TARGET_RLIMIT_NPROC 7 +-#else +-#define TARGET_RLIMIT_NPROC 6 +-#define TARGET_RLIMIT_NOFILE 7 +-#endif +-#define TARGET_RLIMIT_MEMLOCK 8 +-#define TARGET_RLIMIT_AS 9 +-#define TARGET_RLIMIT_LOCKS 10 +-#define TARGET_RLIMIT_SIGPENDING 11 +-#define TARGET_RLIMIT_MSGQUEUE 12 +-#define TARGET_RLIMIT_NICE 13 +-#define TARGET_RLIMIT_RTPRIO 14 +-#endif +- +-struct target_pollfd { +- int fd; /* file descriptor */ +- short events; /* requested events */ +- short revents; /* returned events */ +-}; +- +-/* virtual terminal ioctls */ +-#define TARGET_KIOCSOUND 0x4B2F /* start sound generation (0 for off) */ +-#define TARGET_KDMKTONE 0x4B30 /* generate tone */ +-#define TARGET_KDGKBTYPE 0x4b33 +-#define TARGET_KDSETMODE 0x4b3a +-#define TARGET_KDGKBMODE 0x4b44 +-#define TARGET_KDSKBMODE 0x4b45 +-#define TARGET_KDGKBENT 0x4B46 /* gets one entry in translation table */ +-#define TARGET_KDGKBSENT 0x4B48 /* gets one function key string entry */ +-#define TARGET_KDGKBLED 0x4B64 /* get led flags (not lights) */ +-#define TARGET_KDSKBLED 0x4B65 /* set led flags (not lights) */ +-#define TARGET_KDGETLED 0x4B31 /* return current led state */ +-#define TARGET_KDSETLED 0x4B32 /* set led state [lights, not flags] */ +-#define TARGET_KDSIGACCEPT 0x4B4E +- +-#define TARGET_SIOCATMARK 0x8905 +- +-/* Networking ioctls */ +-#define TARGET_SIOCADDRT 0x890B /* add routing table entry */ +-#define TARGET_SIOCDELRT 0x890C /* delete routing table entry */ +-#define TARGET_SIOCGIFNAME 0x8910 /* get iface name */ +-#define TARGET_SIOCSIFLINK 0x8911 /* set iface channel */ +-#define TARGET_SIOCGIFCONF 0x8912 /* get iface list */ +-#define TARGET_SIOCGIFFLAGS 0x8913 /* get flags */ +-#define TARGET_SIOCSIFFLAGS 0x8914 /* set flags */ +-#define TARGET_SIOCGIFADDR 0x8915 /* get PA address */ +-#define TARGET_SIOCSIFADDR 0x8916 /* set PA address */ +-#define TARGET_SIOCGIFDSTADDR 0x8917 /* get remote PA address */ +-#define TARGET_SIOCSIFDSTADDR 0x8918 /* set remote PA address */ +-#define TARGET_SIOCGIFBRDADDR 0x8919 /* get broadcast PA address */ +-#define TARGET_SIOCSIFBRDADDR 0x891a /* set broadcast PA address */ +-#define TARGET_SIOCGIFNETMASK 0x891b /* get network PA mask */ +-#define TARGET_SIOCSIFNETMASK 0x891c /* set network PA mask */ +-#define TARGET_SIOCGIFMETRIC 0x891d /* get metric */ +-#define TARGET_SIOCSIFMETRIC 0x891e /* set metric */ +-#define TARGET_SIOCGIFMEM 0x891f /* get memory address (BSD) */ +-#define TARGET_SIOCSIFMEM 0x8920 /* set memory address (BSD) */ +-#define TARGET_SIOCGIFMTU 0x8921 /* get MTU size */ +-#define TARGET_SIOCSIFMTU 0x8922 /* set MTU size */ +-#define TARGET_SIOCSIFHWADDR 0x8924 /* set hardware address (NI) */ +-#define TARGET_SIOCGIFENCAP 0x8925 /* get/set slip encapsulation */ +-#define TARGET_SIOCSIFENCAP 0x8926 +-#define TARGET_SIOCGIFHWADDR 0x8927 /* Get hardware address */ +-#define TARGET_SIOCGIFSLAVE 0x8929 /* Driver slaving support */ +-#define TARGET_SIOCSIFSLAVE 0x8930 +-#define TARGET_SIOCADDMULTI 0x8931 /* Multicast address lists */ +-#define TARGET_SIOCDELMULTI 0x8932 +-#define TARGET_SIOCGIFINDEX 0x8933 +- +-/* Bridging control calls */ +-#define TARGET_SIOCGIFBR 0x8940 /* Bridging support */ +-#define TARGET_SIOCSIFBR 0x8941 /* Set bridging options */ +- +-#define TARGET_SIOCGIFTXQLEN 0x8942 /* Get the tx queue length */ +-#define TARGET_SIOCSIFTXQLEN 0x8943 /* Set the tx queue length */ +- +-/* ARP cache control calls. */ +-#define TARGET_OLD_SIOCDARP 0x8950 /* old delete ARP table entry */ +-#define TARGET_OLD_SIOCGARP 0x8951 /* old get ARP table entry */ +-#define TARGET_OLD_SIOCSARP 0x8952 /* old set ARP table entry */ +-#define TARGET_SIOCDARP 0x8953 /* delete ARP table entry */ +-#define TARGET_SIOCGARP 0x8954 /* get ARP table entry */ +-#define TARGET_SIOCSARP 0x8955 /* set ARP table entry */ +- +-/* RARP cache control calls. */ +-#define TARGET_SIOCDRARP 0x8960 /* delete RARP table entry */ +-#define TARGET_SIOCGRARP 0x8961 /* get RARP table entry */ +-#define TARGET_SIOCSRARP 0x8962 /* set RARP table entry */ +- +-/* Driver configuration calls */ +-#define TARGET_SIOCGIFMAP 0x8970 /* Get device parameters */ +-#define TARGET_SIOCSIFMAP 0x8971 /* Set device parameters */ +- +-/* DLCI configuration calls */ +-#define TARGET_SIOCADDDLCI 0x8980 /* Create new DLCI device */ +-#define TARGET_SIOCDELDLCI 0x8981 /* Delete DLCI device */ +- +-/* From */ +- +-#define TARGET_SIOCGIWNAME 0x8B01 /* get name == wireless protocol */ +- +-/* From */ +- +-#define TARGET_BLKROSET TARGET_IO(0x12,93) /* set device read-only (0 = read-write) */ +-#define TARGET_BLKROGET TARGET_IO(0x12,94) /* get read-only status (0 = read_write) */ +-#define TARGET_BLKRRPART TARGET_IO(0x12,95) /* re-read partition table */ +-#define TARGET_BLKGETSIZE TARGET_IO(0x12,96) /* return device size /512 (long *arg) */ +-#define TARGET_BLKFLSBUF TARGET_IO(0x12,97) /* flush buffer cache */ +-#define TARGET_BLKRASET TARGET_IO(0x12,98) /* Set read ahead for block device */ +-#define TARGET_BLKRAGET TARGET_IO(0x12,99) /* get current read ahead setting */ +-#define TARGET_BLKFRASET TARGET_IO(0x12,100)/* set filesystem (mm/filemap.c) read-ahead */ +-#define TARGET_BLKFRAGET TARGET_IO(0x12,101)/* get filesystem (mm/filemap.c) read-ahead */ +-#define TARGET_BLKSECTSET TARGET_IO(0x12,102)/* set max sectors per request (ll_rw_blk.c) */ +-#define TARGET_BLKSECTGET TARGET_IO(0x12,103)/* get max sectors per request (ll_rw_blk.c) */ +-#define TARGET_BLKSSZGET TARGET_IO(0x12,104)/* get block device sector size */ +-#define TARGET_BLKPG TARGET_IO(0x12,105)/* Partition table and disk geometry handling */ +-/* A jump here: 108-111 have been used for various private purposes. */ +-#define TARGET_BLKBSZGET TARGET_IOR(0x12, 112, abi_ulong) +-#define TARGET_BLKBSZSET TARGET_IOW(0x12, 113, abi_ulong) +-#define TARGET_BLKGETSIZE64 TARGET_IOR(0x12,114,abi_ulong) +- /* return device size in bytes +- (u64 *arg) */ +-#define TARGET_FIBMAP TARGET_IO(0x00,1) /* bmap access */ +-#define TARGET_FIGETBSZ TARGET_IO(0x00,2) /* get the block size used for bmap */ +-#define TARGET_FS_IOC_FIEMAP TARGET_IOWR('f',11,struct fiemap) +- +-/* cdrom commands */ +-#define TARGET_CDROMPAUSE 0x5301 /* Pause Audio Operation */ +-#define TARGET_CDROMRESUME 0x5302 /* Resume paused Audio Operation */ +-#define TARGET_CDROMPLAYMSF 0x5303 /* Play Audio MSF (struct cdrom_msf) */ +-#define TARGET_CDROMPLAYTRKIND 0x5304 /* Play Audio Track/index +- (struct cdrom_ti) */ +-#define TARGET_CDROMREADTOCHDR 0x5305 /* Read TOC header +- (struct cdrom_tochdr) */ +-#define TARGET_CDROMREADTOCENTRY 0x5306 /* Read TOC entry +- (struct cdrom_tocentry) */ +-#define TARGET_CDROMSTOP 0x5307 /* Stop the cdrom drive */ +-#define TARGET_CDROMSTART 0x5308 /* Start the cdrom drive */ +-#define TARGET_CDROMEJECT 0x5309 /* Ejects the cdrom media */ +-#define TARGET_CDROMVOLCTRL 0x530a /* Control output volume +- (struct cdrom_volctrl) */ +-#define TARGET_CDROMSUBCHNL 0x530b /* Read subchannel data +- (struct cdrom_subchnl) */ +-#define TARGET_CDROMREADMODE2 0x530c /* Read TARGET_CDROM mode 2 data (2336 Bytes) +- (struct cdrom_read) */ +-#define TARGET_CDROMREADMODE1 0x530d /* Read TARGET_CDROM mode 1 data (2048 Bytes) +- (struct cdrom_read) */ +-#define TARGET_CDROMREADAUDIO 0x530e /* (struct cdrom_read_audio) */ +-#define TARGET_CDROMEJECT_SW 0x530f /* enable(1)/disable(0) auto-ejecting */ +-#define TARGET_CDROMMULTISESSION 0x5310 /* Obtain the start-of-last-session +- address of multi session disks +- (struct cdrom_multisession) */ +-#define TARGET_CDROM_GET_MCN 0x5311 /* Obtain the "Universal Product Code" +- if available (struct cdrom_mcn) */ +-#define TARGET_CDROM_GET_UPC TARGET_CDROM_GET_MCN /* This one is depricated, +- but here anyway for compatibility */ +-#define TARGET_CDROMRESET 0x5312 /* hard-reset the drive */ +-#define TARGET_CDROMVOLREAD 0x5313 /* Get the drive's volume setting +- (struct cdrom_volctrl) */ +-#define TARGET_CDROMREADRAW 0x5314 /* read data in raw mode (2352 Bytes) +- (struct cdrom_read) */ +-/* +- * These ioctls are used only used in aztcd.c and optcd.c +- */ +-#define TARGET_CDROMREADCOOKED 0x5315 /* read data in cooked mode */ +-#define TARGET_CDROMSEEK 0x5316 /* seek msf address */ +- +-/* +- * This ioctl is only used by the scsi-cd driver. +- It is for playing audio in logical block addressing mode. +- */ +-#define TARGET_CDROMPLAYBLK 0x5317 /* (struct cdrom_blk) */ +- +-/* +- * These ioctls are only used in optcd.c +- */ +-#define TARGET_CDROMREADALL 0x5318 /* read all 2646 bytes */ +- +-/* +- * These ioctls are (now) only in ide-cd.c for controlling +- * drive spindown time. They should be implemented in the +- * Uniform driver, via generic packet commands, GPCMD_MODE_SELECT_10, +- * GPCMD_MODE_SENSE_10 and the GPMODE_POWER_PAGE... +- * -Erik +- */ +-#define TARGET_CDROMGETSPINDOWN 0x531d +-#define TARGET_CDROMSETSPINDOWN 0x531e +- +-/* +- * These ioctls are implemented through the uniform CD-ROM driver +- * They _will_ be adopted by all CD-ROM drivers, when all the CD-ROM +- * drivers are eventually ported to the uniform CD-ROM driver interface. +- */ +-#define TARGET_CDROMCLOSETRAY 0x5319 /* pendant of CDROMEJECT */ +-#define TARGET_CDROM_SET_OPTIONS 0x5320 /* Set behavior options */ +-#define TARGET_CDROM_CLEAR_OPTIONS 0x5321 /* Clear behavior options */ +-#define TARGET_CDROM_SELECT_SPEED 0x5322 /* Set the CD-ROM speed */ +-#define TARGET_CDROM_SELECT_DISC 0x5323 /* Select disc (for juke-boxes) */ +-#define TARGET_CDROM_MEDIA_CHANGED 0x5325 /* Check is media changed */ +-#define TARGET_CDROM_DRIVE_STATUS 0x5326 /* Get tray position, etc. */ +-#define TARGET_CDROM_DISC_STATUS 0x5327 /* Get disc type, etc. */ +-#define TARGET_CDROM_CHANGER_NSLOTS 0x5328 /* Get number of slots */ +-#define TARGET_CDROM_LOCKDOOR 0x5329 /* lock or unlock door */ +-#define TARGET_CDROM_DEBUG 0x5330 /* Turn debug messages on/off */ +-#define TARGET_CDROM_GET_CAPABILITY 0x5331 /* get capabilities */ +- +-/* Note that scsi/scsi_ioctl.h also uses 0x5382 - 0x5386. +- * Future CDROM ioctls should be kept below 0x537F +- */ +- +-/* This ioctl is only used by sbpcd at the moment */ +-#define TARGET_CDROMAUDIOBUFSIZ 0x5382 /* set the audio buffer size */ +- /* conflict with SCSI_IOCTL_GET_IDLUN */ +- +-/* DVD-ROM Specific ioctls */ +-#define TARGET_DVD_READ_STRUCT 0x5390 /* Read structure */ +-#define TARGET_DVD_WRITE_STRUCT 0x5391 /* Write structure */ +-#define TARGET_DVD_AUTH 0x5392 /* Authentication */ +- +-#define TARGET_CDROM_SEND_PACKET 0x5393 /* send a packet to the drive */ +-#define TARGET_CDROM_NEXT_WRITABLE 0x5394 /* get next writable block */ +-#define TARGET_CDROM_LAST_WRITTEN 0x5395 /* get last block written on disc */ +- +-/* HD commands */ +- +-/* hd/ide ctl's that pass (arg) ptrs to user space are numbered 0x030n/0x031n */ +-#define TARGET_HDIO_GETGEO 0x0301 /* get device geometry */ +-#define TARGET_HDIO_GET_UNMASKINTR 0x0302 /* get current unmask setting */ +-#define TARGET_HDIO_GET_MULTCOUNT 0x0304 /* get current IDE blockmode setting */ +-#define TARGET_HDIO_GET_KEEPSETTINGS 0x0308 /* get keep-settings-on-reset flag */ +-#define TARGET_HDIO_GET_32BIT 0x0309 /* get current io_32bit setting */ +-#define TARGET_HDIO_GET_NOWERR 0x030a /* get ignore-write-error flag */ +-#define TARGET_HDIO_GET_DMA 0x030b /* get use-dma flag */ +-#define TARGET_HDIO_GET_IDENTITY 0x030d /* get IDE identification info */ +-#define TARGET_HDIO_DRIVE_CMD 0x031f /* execute a special drive command */ +- +-/* hd/ide ctl's that pass (arg) non-ptr values are numbered 0x032n/0x033n */ +-#define TARGET_HDIO_SET_MULTCOUNT 0x0321 /* change IDE blockmode */ +-#define TARGET_HDIO_SET_UNMASKINTR 0x0322 /* permit other irqs during I/O */ +-#define TARGET_HDIO_SET_KEEPSETTINGS 0x0323 /* keep ioctl settings on reset */ +-#define TARGET_HDIO_SET_32BIT 0x0324 /* change io_32bit flags */ +-#define TARGET_HDIO_SET_NOWERR 0x0325 /* change ignore-write-error flag */ +-#define TARGET_HDIO_SET_DMA 0x0326 /* change use-dma flag */ +-#define TARGET_HDIO_SET_PIO_MODE 0x0327 /* reconfig interface to new speed */ +- +-/* loop ioctls */ +-#define TARGET_LOOP_SET_FD 0x4C00 +-#define TARGET_LOOP_CLR_FD 0x4C01 +-#define TARGET_LOOP_SET_STATUS 0x4C02 +-#define TARGET_LOOP_GET_STATUS 0x4C03 +-#define TARGET_LOOP_SET_STATUS64 0x4C04 +-#define TARGET_LOOP_GET_STATUS64 0x4C05 +-#define TARGET_LOOP_CHANGE_FD 0x4C06 +- +-/* fb ioctls */ +-#define TARGET_FBIOGET_VSCREENINFO 0x4600 +-#define TARGET_FBIOPUT_VSCREENINFO 0x4601 +-#define TARGET_FBIOGET_FSCREENINFO 0x4602 +-#define TARGET_FBIOGETCMAP 0x4604 +-#define TARGET_FBIOPUTCMAP 0x4605 +-#define TARGET_FBIOPAN_DISPLAY 0x4606 +-#define TARGET_FBIOGET_CON2FBMAP 0x460F +-#define TARGET_FBIOPUT_CON2FBMAP 0x4610 +- +-/* vt ioctls */ +-#define TARGET_VT_OPENQRY 0x5600 +-#define TARGET_VT_GETSTATE 0x5603 +-#define TARGET_VT_ACTIVATE 0x5606 +-#define TARGET_VT_WAITACTIVE 0x5607 +-#define TARGET_VT_LOCKSWITCH 0x560b +-#define TARGET_VT_UNLOCKSWITCH 0x560c +-#define TARGET_VT_GETMODE 0x5601 +-#define TARGET_VT_SETMODE 0x5602 +-#define TARGET_VT_RELDISP 0x5605 +-#define TARGET_VT_DISALLOCATE 0x5608 +- +-/* device mapper */ +-#define TARGET_DM_VERSION TARGET_IOWRU(0xfd, 0x00) +-#define TARGET_DM_REMOVE_ALL TARGET_IOWRU(0xfd, 0x01) +-#define TARGET_DM_LIST_DEVICES TARGET_IOWRU(0xfd, 0x02) +-#define TARGET_DM_DEV_CREATE TARGET_IOWRU(0xfd, 0x03) +-#define TARGET_DM_DEV_REMOVE TARGET_IOWRU(0xfd, 0x04) +-#define TARGET_DM_DEV_RENAME TARGET_IOWRU(0xfd, 0x05) +-#define TARGET_DM_DEV_SUSPEND TARGET_IOWRU(0xfd, 0x06) +-#define TARGET_DM_DEV_STATUS TARGET_IOWRU(0xfd, 0x07) +-#define TARGET_DM_DEV_WAIT TARGET_IOWRU(0xfd, 0x08) +-#define TARGET_DM_TABLE_LOAD TARGET_IOWRU(0xfd, 0x09) +-#define TARGET_DM_TABLE_CLEAR TARGET_IOWRU(0xfd, 0x0a) +-#define TARGET_DM_TABLE_DEPS TARGET_IOWRU(0xfd, 0x0b) +-#define TARGET_DM_TABLE_STATUS TARGET_IOWRU(0xfd, 0x0c) +-#define TARGET_DM_LIST_VERSIONS TARGET_IOWRU(0xfd, 0x0d) +-#define TARGET_DM_TARGET_MSG TARGET_IOWRU(0xfd, 0x0e) +-#define TARGET_DM_DEV_SET_GEOMETRY TARGET_IOWRU(0xfd, 0x0f) +- +-/* from asm/termbits.h */ +- +-#define TARGET_NCC 8 +-struct target_termio { +- unsigned short c_iflag; /* input mode flags */ +- unsigned short c_oflag; /* output mode flags */ +- unsigned short c_cflag; /* control mode flags */ +- unsigned short c_lflag; /* local mode flags */ +- unsigned char c_line; /* line discipline */ +- unsigned char c_cc[TARGET_NCC]; /* control characters */ +-}; +- +-struct target_winsize { +- unsigned short ws_row; +- unsigned short ws_col; +- unsigned short ws_xpixel; +- unsigned short ws_ypixel; +-}; +- +-#include "termbits.h" +- +-#if defined(TARGET_MIPS) +-#define TARGET_PROT_SEM 0x10 +-#else +-#define TARGET_PROT_SEM 0x08 +-#endif +- +-/* Common */ +-#define TARGET_MAP_SHARED 0x01 /* Share changes */ +-#define TARGET_MAP_PRIVATE 0x02 /* Changes are private */ +-#define TARGET_MAP_TYPE 0x0f /* Mask for type of mapping */ +- +-/* Target specific */ +-#if defined(TARGET_MIPS) +-#define TARGET_MAP_FIXED 0x10 /* Interpret addr exactly */ +-#define TARGET_MAP_ANONYMOUS 0x0800 /* don't use a file */ +-#define TARGET_MAP_GROWSDOWN 0x1000 /* stack-like segment */ +-#define TARGET_MAP_DENYWRITE 0x2000 /* ETXTBSY */ +-#define TARGET_MAP_EXECUTABLE 0x4000 /* mark it as an executable */ +-#define TARGET_MAP_LOCKED 0x8000 /* pages are locked */ +-#define TARGET_MAP_NORESERVE 0x0400 /* don't check for reservations */ +-#define TARGET_MAP_POPULATE 0x10000 /* populate (prefault) pagetables */ +-#define TARGET_MAP_NONBLOCK 0x20000 /* do not block on IO */ +-#elif defined(TARGET_PPC) +-#define TARGET_MAP_FIXED 0x10 /* Interpret addr exactly */ +-#define TARGET_MAP_ANONYMOUS 0x20 /* don't use a file */ +-#define TARGET_MAP_GROWSDOWN 0x0100 /* stack-like segment */ +-#define TARGET_MAP_DENYWRITE 0x0800 /* ETXTBSY */ +-#define TARGET_MAP_EXECUTABLE 0x1000 /* mark it as an executable */ +-#define TARGET_MAP_LOCKED 0x0080 /* pages are locked */ +-#define TARGET_MAP_NORESERVE 0x0040 /* don't check for reservations */ +-#define TARGET_MAP_POPULATE 0x8000 /* populate (prefault) pagetables */ +-#define TARGET_MAP_NONBLOCK 0x10000 /* do not block on IO */ +-#elif defined(TARGET_ALPHA) +-#define TARGET_MAP_ANONYMOUS 0x10 /* don't use a file */ +-#define TARGET_MAP_FIXED 0x100 /* Interpret addr exactly */ +-#define TARGET_MAP_GROWSDOWN 0x01000 /* stack-like segment */ +-#define TARGET_MAP_DENYWRITE 0x02000 /* ETXTBSY */ +-#define TARGET_MAP_EXECUTABLE 0x04000 /* mark it as an executable */ +-#define TARGET_MAP_LOCKED 0x08000 /* lock the mapping */ +-#define TARGET_MAP_NORESERVE 0x10000 /* no check for reservations */ +-#define TARGET_MAP_POPULATE 0x20000 /* pop (prefault) pagetables */ +-#define TARGET_MAP_NONBLOCK 0x40000 /* do not block on IO */ +-#else +-#define TARGET_MAP_FIXED 0x10 /* Interpret addr exactly */ +-#define TARGET_MAP_ANONYMOUS 0x20 /* don't use a file */ +-#define TARGET_MAP_GROWSDOWN 0x0100 /* stack-like segment */ +-#define TARGET_MAP_DENYWRITE 0x0800 /* ETXTBSY */ +-#define TARGET_MAP_EXECUTABLE 0x1000 /* mark it as an executable */ +-#define TARGET_MAP_LOCKED 0x2000 /* pages are locked */ +-#define TARGET_MAP_NORESERVE 0x4000 /* don't check for reservations */ +-#define TARGET_MAP_POPULATE 0x8000 /* populate (prefault) pagetables */ +-#define TARGET_MAP_NONBLOCK 0x10000 /* do not block on IO */ +-#define TARGET_MAP_UNINITIALIZED 0x4000000 /* for anonymous mmap, memory could be uninitialized */ +-#endif +- +-#if (defined(TARGET_I386) && defined(TARGET_ABI32)) \ +- || (defined(TARGET_ARM) && defined(TARGET_ABI32)) \ +- || defined(TARGET_CRIS) || defined(TARGET_UNICORE32) +-struct target_stat { +- unsigned short st_dev; +- unsigned short __pad1; +- abi_ulong st_ino; +- unsigned short st_mode; +- unsigned short st_nlink; +- unsigned short st_uid; +- unsigned short st_gid; +- unsigned short st_rdev; +- unsigned short __pad2; +- abi_ulong st_size; +- abi_ulong st_blksize; +- abi_ulong st_blocks; +- abi_ulong target_st_atime; +- abi_ulong __unused1; +- abi_ulong target_st_mtime; +- abi_ulong __unused2; +- abi_ulong target_st_ctime; +- abi_ulong __unused3; +- abi_ulong __unused4; +- abi_ulong __unused5; +-}; +- +-/* This matches struct stat64 in glibc2.1, hence the absolutely +- * insane amounts of padding around dev_t's. +- */ +-#define TARGET_HAS_STRUCT_STAT64 +-struct target_stat64 { +- unsigned short st_dev; +- unsigned char __pad0[10]; +- +-#define TARGET_STAT64_HAS_BROKEN_ST_INO 1 +- abi_ulong __st_ino; +- +- unsigned int st_mode; +- unsigned int st_nlink; +- +- abi_ulong st_uid; +- abi_ulong st_gid; +- +- unsigned short st_rdev; +- unsigned char __pad3[10]; +- +- long long st_size; +- abi_ulong st_blksize; +- +- abi_ulong st_blocks; /* Number 512-byte blocks allocated. */ +- abi_ulong __pad4; /* future possible st_blocks high bits */ +- +- abi_ulong target_st_atime; +- abi_ulong __pad5; +- +- abi_ulong target_st_mtime; +- abi_ulong __pad6; +- +- abi_ulong target_st_ctime; +- abi_ulong __pad7; /* will be high 32 bits of ctime someday */ +- +- unsigned long long st_ino; +-} QEMU_PACKED; +- +-#ifdef TARGET_ARM +-#define TARGET_HAS_STRUCT_STAT64 +-struct target_eabi_stat64 { +- unsigned long long st_dev; +- unsigned int __pad1; +- abi_ulong __st_ino; +- unsigned int st_mode; +- unsigned int st_nlink; +- +- abi_ulong st_uid; +- abi_ulong st_gid; +- +- unsigned long long st_rdev; +- unsigned int __pad2[2]; +- +- long long st_size; +- abi_ulong st_blksize; +- unsigned int __pad3; +- unsigned long long st_blocks; +- +- abi_ulong target_st_atime; +- abi_ulong target_st_atime_nsec; +- +- abi_ulong target_st_mtime; +- abi_ulong target_st_mtime_nsec; +- +- abi_ulong target_st_ctime; +- abi_ulong target_st_ctime_nsec; +- +- unsigned long long st_ino; +-} QEMU_PACKED; +-#endif +- +-#elif defined(TARGET_SPARC64) && !defined(TARGET_ABI32) +-struct target_stat { +- unsigned int st_dev; +- abi_ulong st_ino; +- unsigned int st_mode; +- unsigned int st_nlink; +- unsigned int st_uid; +- unsigned int st_gid; +- unsigned int st_rdev; +- abi_long st_size; +- abi_long target_st_atime; +- abi_long target_st_mtime; +- abi_long target_st_ctime; +- abi_long st_blksize; +- abi_long st_blocks; +- abi_ulong __unused4[2]; +-}; +- +-#define TARGET_HAS_STRUCT_STAT64 +-struct target_stat64 { +- unsigned char __pad0[6]; +- unsigned short st_dev; +- +- uint64_t st_ino; +- uint64_t st_nlink; +- +- unsigned int st_mode; +- +- unsigned int st_uid; +- unsigned int st_gid; +- +- unsigned char __pad2[6]; +- unsigned short st_rdev; +- +- int64_t st_size; +- int64_t st_blksize; +- +- unsigned char __pad4[4]; +- unsigned int st_blocks; +- +- abi_ulong target_st_atime; +- abi_ulong __unused1; +- +- abi_ulong target_st_mtime; +- abi_ulong __unused2; +- +- abi_ulong target_st_ctime; +- abi_ulong __unused3; +- +- abi_ulong __unused4[3]; +-}; +- +-#elif defined(TARGET_SPARC) +- +-struct target_stat { +- unsigned short st_dev; +- abi_ulong st_ino; +- unsigned short st_mode; +- short st_nlink; +- unsigned short st_uid; +- unsigned short st_gid; +- unsigned short st_rdev; +- abi_long st_size; +- abi_long target_st_atime; +- abi_ulong __unused1; +- abi_long target_st_mtime; +- abi_ulong __unused2; +- abi_long target_st_ctime; +- abi_ulong __unused3; +- abi_long st_blksize; +- abi_long st_blocks; +- abi_ulong __unused4[2]; +-}; +- +-#define TARGET_HAS_STRUCT_STAT64 +-struct target_stat64 { +- unsigned char __pad0[6]; +- unsigned short st_dev; +- +- uint64_t st_ino; +- +- unsigned int st_mode; +- unsigned int st_nlink; +- +- unsigned int st_uid; +- unsigned int st_gid; +- +- unsigned char __pad2[6]; +- unsigned short st_rdev; +- +- unsigned char __pad3[8]; +- +- int64_t st_size; +- unsigned int st_blksize; +- +- unsigned char __pad4[8]; +- unsigned int st_blocks; +- +- unsigned int target_st_atime; +- unsigned int __unused1; +- +- unsigned int target_st_mtime; +- unsigned int __unused2; +- +- unsigned int target_st_ctime; +- unsigned int __unused3; +- +- unsigned int __unused4; +- unsigned int __unused5; +-}; +- +-#elif defined(TARGET_PPC) +- +-struct target_stat { +- abi_ulong st_dev; +- abi_ulong st_ino; +-#if defined(TARGET_PPC64) && !defined(TARGET_ABI32) +- abi_ulong st_nlink; +- unsigned int st_mode; +-#else +- unsigned int st_mode; +- unsigned short st_nlink; +-#endif +- unsigned int st_uid; +- unsigned int st_gid; +- abi_ulong st_rdev; +- abi_ulong st_size; +- abi_ulong st_blksize; +- abi_ulong st_blocks; +- abi_ulong target_st_atime; +- abi_ulong target_st_atime_nsec; +- abi_ulong target_st_mtime; +- abi_ulong target_st_mtime_nsec; +- abi_ulong target_st_ctime; +- abi_ulong target_st_ctime_nsec; +- abi_ulong __unused4; +- abi_ulong __unused5; +-#if defined(TARGET_PPC64) && !defined(TARGET_ABI32) +- abi_ulong __unused6; +-#endif +-}; +- +-#if !defined(TARGET_PPC64) || defined(TARGET_ABI32) +-#define TARGET_HAS_STRUCT_STAT64 +-struct QEMU_PACKED target_stat64 { +- unsigned long long st_dev; +- unsigned long long st_ino; +- unsigned int st_mode; +- unsigned int st_nlink; +- unsigned int st_uid; +- unsigned int st_gid; +- unsigned long long st_rdev; +- unsigned long long __pad0; +- long long st_size; +- int st_blksize; +- unsigned int __pad1; +- long long st_blocks; /* Number 512-byte blocks allocated. */ +- int target_st_atime; +- unsigned int target_st_atime_nsec; +- int target_st_mtime; +- unsigned int target_st_mtime_nsec; +- int target_st_ctime; +- unsigned int target_st_ctime_nsec; +- unsigned int __unused4; +- unsigned int __unused5; +-}; +-#endif +- +-#elif defined(TARGET_MICROBLAZE) +- +-struct target_stat { +- abi_ulong st_dev; +- abi_ulong st_ino; +- unsigned int st_mode; +- unsigned short st_nlink; +- unsigned int st_uid; +- unsigned int st_gid; +- abi_ulong st_rdev; +- abi_ulong st_size; +- abi_ulong st_blksize; +- abi_ulong st_blocks; +- abi_ulong target_st_atime; +- abi_ulong target_st_atime_nsec; +- abi_ulong target_st_mtime; +- abi_ulong target_st_mtime_nsec; +- abi_ulong target_st_ctime; +- abi_ulong target_st_ctime_nsec; +- abi_ulong __unused4; +- abi_ulong __unused5; +-}; +- +-/* FIXME: Microblaze no-mmu user-space has a difference stat64 layout... */ +-#define TARGET_HAS_STRUCT_STAT64 +-struct QEMU_PACKED target_stat64 { +- uint64_t st_dev; +-#define TARGET_STAT64_HAS_BROKEN_ST_INO 1 +- uint32_t pad0; +- uint32_t __st_ino; +- +- uint32_t st_mode; +- uint32_t st_nlink; +- uint32_t st_uid; +- uint32_t st_gid; +- uint64_t st_rdev; +- uint64_t __pad1; +- +- int64_t st_size; +- int32_t st_blksize; +- uint32_t __pad2; +- int64_t st_blocks; /* Number 512-byte blocks allocated. */ +- +- int target_st_atime; +- unsigned int target_st_atime_nsec; +- int target_st_mtime; +- unsigned int target_st_mtime_nsec; +- int target_st_ctime; +- unsigned int target_st_ctime_nsec; +- uint64_t st_ino; +-}; +- +-#elif defined(TARGET_M68K) +- +-struct target_stat { +- unsigned short st_dev; +- unsigned short __pad1; +- abi_ulong st_ino; +- unsigned short st_mode; +- unsigned short st_nlink; +- unsigned short st_uid; +- unsigned short st_gid; +- unsigned short st_rdev; +- unsigned short __pad2; +- abi_ulong st_size; +- abi_ulong st_blksize; +- abi_ulong st_blocks; +- abi_ulong target_st_atime; +- abi_ulong __unused1; +- abi_ulong target_st_mtime; +- abi_ulong __unused2; +- abi_ulong target_st_ctime; +- abi_ulong __unused3; +- abi_ulong __unused4; +- abi_ulong __unused5; +-}; +- +-/* This matches struct stat64 in glibc2.1, hence the absolutely +- * insane amounts of padding around dev_t's. +- */ +-#define TARGET_HAS_STRUCT_STAT64 +-struct target_stat64 { +- unsigned long long st_dev; +- unsigned char __pad1[2]; +- +-#define TARGET_STAT64_HAS_BROKEN_ST_INO 1 +- abi_ulong __st_ino; +- +- unsigned int st_mode; +- unsigned int st_nlink; +- +- abi_ulong st_uid; +- abi_ulong st_gid; +- +- unsigned long long st_rdev; +- unsigned char __pad3[2]; +- +- long long st_size; +- abi_ulong st_blksize; +- +- abi_ulong __pad4; /* future possible st_blocks high bits */ +- abi_ulong st_blocks; /* Number 512-byte blocks allocated. */ +- +- abi_ulong target_st_atime; +- abi_ulong target_st_atime_nsec; +- +- abi_ulong target_st_mtime; +- abi_ulong target_st_mtime_nsec; +- +- abi_ulong target_st_ctime; +- abi_ulong target_st_ctime_nsec; +- +- unsigned long long st_ino; +-} QEMU_PACKED; +- +-#elif defined(TARGET_ABI_MIPSN64) +- +-/* The memory layout is the same as of struct stat64 of the 32-bit kernel. */ +-struct target_stat { +- unsigned int st_dev; +- unsigned int st_pad0[3]; /* Reserved for st_dev expansion */ +- +- abi_ulong st_ino; +- +- unsigned int st_mode; +- unsigned int st_nlink; +- +- int st_uid; +- int st_gid; +- +- unsigned int st_rdev; +- unsigned int st_pad1[3]; /* Reserved for st_rdev expansion */ +- +- abi_ulong st_size; +- +- /* +- * Actually this should be timestruc_t st_atime, st_mtime and st_ctime +- * but we don't have it under Linux. +- */ +- unsigned int target_st_atime; +- unsigned int target_st_atime_nsec; +- +- unsigned int target_st_mtime; +- unsigned int target_st_mtime_nsec; +- +- unsigned int target_st_ctime; +- unsigned int target_st_ctime_nsec; +- +- unsigned int st_blksize; +- unsigned int st_pad2; +- +- abi_ulong st_blocks; +-}; +- +-#elif defined(TARGET_ABI_MIPSN32) +- +-struct target_stat { +- abi_ulong st_dev; +- abi_ulong st_pad0[3]; /* Reserved for st_dev expansion */ +- uint64_t st_ino; +- unsigned int st_mode; +- unsigned int st_nlink; +- int st_uid; +- int st_gid; +- abi_ulong st_rdev; +- abi_ulong st_pad1[3]; /* Reserved for st_rdev expansion */ +- int64_t st_size; +- abi_long target_st_atime; +- abi_ulong target_st_atime_nsec; /* Reserved for st_atime expansion */ +- abi_long target_st_mtime; +- abi_ulong target_st_mtime_nsec; /* Reserved for st_mtime expansion */ +- abi_long target_st_ctime; +- abi_ulong target_st_ctime_nsec; /* Reserved for st_ctime expansion */ +- abi_ulong st_blksize; +- abi_ulong st_pad2; +- int64_t st_blocks; +-}; +- +-#elif defined(TARGET_ABI_MIPSO32) +- +-struct target_stat { +- unsigned st_dev; +- abi_long st_pad1[3]; /* Reserved for network id */ +- abi_ulong st_ino; +- unsigned int st_mode; +- unsigned int st_nlink; +- int st_uid; +- int st_gid; +- unsigned st_rdev; +- abi_long st_pad2[2]; +- abi_long st_size; +- abi_long st_pad3; +- /* +- * Actually this should be timestruc_t st_atime, st_mtime and st_ctime +- * but we don't have it under Linux. +- */ +- abi_long target_st_atime; +- abi_long target_st_atime_nsec; +- abi_long target_st_mtime; +- abi_long target_st_mtime_nsec; +- abi_long target_st_ctime; +- abi_long target_st_ctime_nsec; +- abi_long st_blksize; +- abi_long st_blocks; +- abi_long st_pad4[14]; +-}; +- +-/* +- * This matches struct stat64 in glibc2.1, hence the absolutely insane +- * amounts of padding around dev_t's. The memory layout is the same as of +- * struct stat of the 64-bit kernel. +- */ +- +-#define TARGET_HAS_STRUCT_STAT64 +-struct target_stat64 { +- abi_ulong st_dev; +- abi_ulong st_pad0[3]; /* Reserved for st_dev expansion */ +- +- uint64_t st_ino; +- +- unsigned int st_mode; +- unsigned int st_nlink; +- +- int st_uid; +- int st_gid; +- +- abi_ulong st_rdev; +- abi_ulong st_pad1[3]; /* Reserved for st_rdev expansion */ +- +- int64_t st_size; +- +- /* +- * Actually this should be timestruc_t st_atime, st_mtime and st_ctime +- * but we don't have it under Linux. +- */ +- abi_long target_st_atime; +- abi_ulong target_st_atime_nsec; /* Reserved for st_atime expansion */ +- +- abi_long target_st_mtime; +- abi_ulong target_st_mtime_nsec; /* Reserved for st_mtime expansion */ +- +- abi_long target_st_ctime; +- abi_ulong target_st_ctime_nsec; /* Reserved for st_ctime expansion */ +- +- abi_ulong st_blksize; +- abi_ulong st_pad2; +- +- int64_t st_blocks; +-}; +- +-#elif defined(TARGET_ALPHA) +- +-struct target_stat { +- unsigned int st_dev; +- unsigned int st_ino; +- unsigned int st_mode; +- unsigned int st_nlink; +- unsigned int st_uid; +- unsigned int st_gid; +- unsigned int st_rdev; +- abi_long st_size; +- abi_ulong target_st_atime; +- abi_ulong target_st_mtime; +- abi_ulong target_st_ctime; +- unsigned int st_blksize; +- unsigned int st_blocks; +- unsigned int st_flags; +- unsigned int st_gen; +-}; +- +-#define TARGET_HAS_STRUCT_STAT64 +-struct target_stat64 { +- abi_ulong st_dev; +- abi_ulong st_ino; +- abi_ulong st_rdev; +- abi_long st_size; +- abi_ulong st_blocks; +- +- unsigned int st_mode; +- unsigned int st_uid; +- unsigned int st_gid; +- unsigned int st_blksize; +- unsigned int st_nlink; +- unsigned int __pad0; +- +- abi_ulong target_st_atime; +- abi_ulong target_st_atime_nsec; +- abi_ulong target_st_mtime; +- abi_ulong target_st_mtime_nsec; +- abi_ulong target_st_ctime; +- abi_ulong target_st_ctime_nsec; +- abi_long __unused[3]; +-}; +- +-#elif defined(TARGET_SH4) +- +-struct target_stat { +- abi_ulong st_dev; +- abi_ulong st_ino; +- unsigned short st_mode; +- unsigned short st_nlink; +- unsigned short st_uid; +- unsigned short st_gid; +- abi_ulong st_rdev; +- abi_ulong st_size; +- abi_ulong st_blksize; +- abi_ulong st_blocks; +- abi_ulong target_st_atime; +- abi_ulong target_st_atime_nsec; +- abi_ulong target_st_mtime; +- abi_ulong target_st_mtime_nsec; +- abi_ulong target_st_ctime; +- abi_ulong target_st_ctime_nsec; +- abi_ulong __unused4; +- abi_ulong __unused5; +-}; +- +-/* This matches struct stat64 in glibc2.1, hence the absolutely +- * insane amounts of padding around dev_t's. +- */ +-#define TARGET_HAS_STRUCT_STAT64 +-struct QEMU_PACKED target_stat64 { +- unsigned long long st_dev; +- unsigned char __pad0[4]; +- +-#define TARGET_STAT64_HAS_BROKEN_ST_INO 1 +- abi_ulong __st_ino; +- +- unsigned int st_mode; +- unsigned int st_nlink; +- +- abi_ulong st_uid; +- abi_ulong st_gid; +- +- unsigned long long st_rdev; +- unsigned char __pad3[4]; +- +- long long st_size; +- abi_ulong st_blksize; +- +- unsigned long long st_blocks; /* Number 512-byte blocks allocated. */ +- +- abi_ulong target_st_atime; +- abi_ulong target_st_atime_nsec; +- +- abi_ulong target_st_mtime; +- abi_ulong target_st_mtime_nsec; +- +- abi_ulong target_st_ctime; +- abi_ulong target_st_ctime_nsec; +- +- unsigned long long st_ino; +-}; +- +-#elif defined(TARGET_I386) && !defined(TARGET_ABI32) +-struct target_stat { +- abi_ulong st_dev; +- abi_ulong st_ino; +- abi_ulong st_nlink; +- +- unsigned int st_mode; +- unsigned int st_uid; +- unsigned int st_gid; +- unsigned int __pad0; +- abi_ulong st_rdev; +- abi_long st_size; +- abi_long st_blksize; +- abi_long st_blocks; /* Number 512-byte blocks allocated. */ +- +- abi_ulong target_st_atime; +- abi_ulong target_st_atime_nsec; +- abi_ulong target_st_mtime; +- abi_ulong target_st_mtime_nsec; +- abi_ulong target_st_ctime; +- abi_ulong target_st_ctime_nsec; +- +- abi_long __unused[3]; +-}; +-#elif defined(TARGET_S390X) +-struct target_stat { +- abi_ulong st_dev; +- abi_ulong st_ino; +- abi_ulong st_nlink; +- unsigned int st_mode; +- unsigned int st_uid; +- unsigned int st_gid; +- unsigned int __pad1; +- abi_ulong st_rdev; +- abi_ulong st_size; +- abi_ulong target_st_atime; +- abi_ulong target_st_atime_nsec; +- abi_ulong target_st_mtime; +- abi_ulong target_st_mtime_nsec; +- abi_ulong target_st_ctime; +- abi_ulong target_st_ctime_nsec; +- abi_ulong st_blksize; +- abi_long st_blocks; +- abi_ulong __unused[3]; +-}; +-#elif defined(TARGET_AARCH64) +-struct target_stat { +- abi_ulong st_dev; +- abi_ulong st_ino; +- unsigned int st_mode; +- unsigned int st_nlink; +- unsigned int st_uid; +- unsigned int st_gid; +- abi_ulong st_rdev; +- abi_ulong _pad1; +- abi_long st_size; +- int st_blksize; +- int __pad2; +- abi_long st_blocks; +- abi_long target_st_atime; +- abi_ulong target_st_atime_nsec; +- abi_long target_st_mtime; +- abi_ulong target_st_mtime_nsec; +- abi_long target_st_ctime; +- abi_ulong target_st_ctime_nsec; +- unsigned int __unused[2]; +-}; +-#elif defined(TARGET_OPENRISC) +- +-/* These are the asm-generic versions of the stat and stat64 structures */ +- +-struct target_stat { +- abi_ulong st_dev; +- abi_ulong st_ino; +- unsigned int st_mode; +- unsigned int st_nlink; +- unsigned int st_uid; +- unsigned int st_gid; +- abi_ulong st_rdev; +- abi_ulong __pad1; +- abi_long st_size; +- int st_blksize; +- int __pad2; +- abi_long st_blocks; +- abi_long target_st_atime; +- abi_ulong target_st_atime_nsec; +- abi_long target_st_mtime; +- abi_ulong target_st_mtime_nsec; +- abi_long target_st_ctime; +- abi_ulong target_st_ctime_nsec; +- unsigned int __unused4; +- unsigned int __unused5; +-}; +- +-#define TARGET_HAS_STRUCT_STAT64 +-struct target_stat64 { +- uint64_t st_dev; +- uint64_t st_ino; +- unsigned int st_mode; +- unsigned int st_nlink; +- unsigned int st_uid; +- unsigned int st_gid; +- uint64_t st_rdev; +- uint64_t __pad1; +- int64_t st_size; +- int st_blksize; +- int __pad2; +- int64_t st_blocks; +- int target_st_atime; +- unsigned int target_st_atime_nsec; +- int target_st_mtime; +- unsigned int target_st_mtime_nsec; +- int target_st_ctime; +- unsigned int target_st_ctime_nsec; +- unsigned int __unused4; +- unsigned int __unused5; +-}; +- +-#else +-#error unsupported CPU +-#endif +- +-typedef struct { +- int val[2]; +-} target_fsid_t; +- +-#ifdef TARGET_MIPS +-#ifdef TARGET_ABI_MIPSN32 +-struct target_statfs { +- int32_t f_type; +- int32_t f_bsize; +- int32_t f_frsize; /* Fragment size - unsupported */ +- int32_t f_blocks; +- int32_t f_bfree; +- int32_t f_files; +- int32_t f_ffree; +- int32_t f_bavail; +- +- /* Linux specials */ +- target_fsid_t f_fsid; +- int32_t f_namelen; +- int32_t f_spare[6]; +-}; +-#else +-struct target_statfs { +- abi_long f_type; +- abi_long f_bsize; +- abi_long f_frsize; /* Fragment size - unsupported */ +- abi_long f_blocks; +- abi_long f_bfree; +- abi_long f_files; +- abi_long f_ffree; +- abi_long f_bavail; +- +- /* Linux specials */ +- target_fsid_t f_fsid; +- abi_long f_namelen; +- abi_long f_spare[6]; +-}; +-#endif +- +-struct target_statfs64 { +- uint32_t f_type; +- uint32_t f_bsize; +- uint32_t f_frsize; /* Fragment size - unsupported */ +- uint32_t __pad; +- uint64_t f_blocks; +- uint64_t f_bfree; +- uint64_t f_files; +- uint64_t f_ffree; +- uint64_t f_bavail; +- target_fsid_t f_fsid; +- uint32_t f_namelen; +- uint32_t f_spare[6]; +-}; +-#elif (defined(TARGET_PPC64) || defined(TARGET_X86_64) || \ +- defined(TARGET_SPARC64) || defined(TARGET_AARCH64)) && \ +- !defined(TARGET_ABI32) +-struct target_statfs { +- abi_long f_type; +- abi_long f_bsize; +- abi_long f_blocks; +- abi_long f_bfree; +- abi_long f_bavail; +- abi_long f_files; +- abi_long f_ffree; +- target_fsid_t f_fsid; +- abi_long f_namelen; +- abi_long f_frsize; +- abi_long f_spare[5]; +-}; +- +-struct target_statfs64 { +- abi_long f_type; +- abi_long f_bsize; +- abi_long f_blocks; +- abi_long f_bfree; +- abi_long f_bavail; +- abi_long f_files; +- abi_long f_ffree; +- target_fsid_t f_fsid; +- abi_long f_namelen; +- abi_long f_frsize; +- abi_long f_spare[5]; +-}; +-#elif defined(TARGET_S390X) +-struct target_statfs { +- int32_t f_type; +- int32_t f_bsize; +- abi_long f_blocks; +- abi_long f_bfree; +- abi_long f_bavail; +- abi_long f_files; +- abi_long f_ffree; +- kernel_fsid_t f_fsid; +- int32_t f_namelen; +- int32_t f_frsize; +- int32_t f_spare[5]; +-}; +- +-struct target_statfs64 { +- int32_t f_type; +- int32_t f_bsize; +- abi_long f_blocks; +- abi_long f_bfree; +- abi_long f_bavail; +- abi_long f_files; +- abi_long f_ffree; +- kernel_fsid_t f_fsid; +- int32_t f_namelen; +- int32_t f_frsize; +- int32_t f_spare[5]; +-}; +-#else +-struct target_statfs { +- uint32_t f_type; +- uint32_t f_bsize; +- uint32_t f_blocks; +- uint32_t f_bfree; +- uint32_t f_bavail; +- uint32_t f_files; +- uint32_t f_ffree; +- target_fsid_t f_fsid; +- uint32_t f_namelen; +- uint32_t f_frsize; +- uint32_t f_spare[5]; +-}; +- +-struct target_statfs64 { +- uint32_t f_type; +- uint32_t f_bsize; +- uint64_t f_blocks; +- uint64_t f_bfree; +- uint64_t f_bavail; +- uint64_t f_files; +- uint64_t f_ffree; +- target_fsid_t f_fsid; +- uint32_t f_namelen; +- uint32_t f_frsize; +- uint32_t f_spare[5]; +-}; +-#endif +- +- +-#define TARGET_F_DUPFD 0 /* dup */ +-#define TARGET_F_GETFD 1 /* get close_on_exec */ +-#define TARGET_F_SETFD 2 /* set/clear close_on_exec */ +-#define TARGET_F_GETFL 3 /* get file->f_flags */ +-#define TARGET_F_SETFL 4 /* set file->f_flags */ +- +-#if defined(TARGET_ALPHA) +-#define TARGET_F_GETLK 7 +-#define TARGET_F_SETLK 8 +-#define TARGET_F_SETLKW 9 +-#define TARGET_F_SETOWN 5 /* for sockets. */ +-#define TARGET_F_GETOWN 6 /* for sockets. */ +- +-#define TARGET_F_RDLCK 1 +-#define TARGET_F_WRLCK 2 +-#define TARGET_F_UNLCK 8 +-#define TARGET_F_EXLCK 16 +-#define TARGET_F_SHLCK 32 +-#elif defined(TARGET_MIPS) +-#define TARGET_F_GETLK 14 +-#define TARGET_F_SETLK 6 +-#define TARGET_F_SETLKW 7 +-#define TARGET_F_SETOWN 24 /* for sockets. */ +-#define TARGET_F_GETOWN 25 /* for sockets. */ +-#else +-#define TARGET_F_GETLK 5 +-#define TARGET_F_SETLK 6 +-#define TARGET_F_SETLKW 7 +-#define TARGET_F_SETOWN 8 /* for sockets. */ +-#define TARGET_F_GETOWN 9 /* for sockets. */ +-#endif +-#define TARGET_F_SETOWN_EX 15 +-#define TARGET_F_GETOWN_EX 16 +- +-#ifndef TARGET_F_RDLCK +-#define TARGET_F_RDLCK 0 +-#define TARGET_F_WRLCK 1 +-#define TARGET_F_UNLCK 2 +-#endif +- +-#ifndef TARGET_F_EXLCK +-#define TARGET_F_EXLCK 4 +-#define TARGET_F_SHLCK 8 +-#endif +- +- +-#define TARGET_F_SETSIG 10 /* for sockets. */ +-#define TARGET_F_GETSIG 11 /* for sockets. */ +- +-#if defined(TARGET_MIPS) +-#define TARGET_F_GETLK64 33 /* using 'struct flock64' */ +-#define TARGET_F_SETLK64 34 +-#define TARGET_F_SETLKW64 35 +-#else +-#define TARGET_F_GETLK64 12 /* using 'struct flock64' */ +-#define TARGET_F_SETLK64 13 +-#define TARGET_F_SETLKW64 14 +-#endif +- +-#define TARGET_F_LINUX_SPECIFIC_BASE 1024 +-#define TARGET_F_SETLEASE (TARGET_F_LINUX_SPECIFIC_BASE + 0) +-#define TARGET_F_GETLEASE (TARGET_F_LINUX_SPECIFIC_BASE + 1) +-#define TARGET_F_DUPFD_CLOEXEC (TARGET_F_LINUX_SPECIFIC_BASE + 6) +-#define TARGET_F_NOTIFY (TARGET_F_LINUX_SPECIFIC_BASE+2) +- +-#if defined(TARGET_ALPHA) +-#define TARGET_O_NONBLOCK 04 +-#define TARGET_O_APPEND 010 +-#define TARGET_O_CREAT 01000 /* not fcntl */ +-#define TARGET_O_TRUNC 02000 /* not fcntl */ +-#define TARGET_O_EXCL 04000 /* not fcntl */ +-#define TARGET_O_NOCTTY 010000 /* not fcntl */ +-#define TARGET_O_DSYNC 040000 +-#define TARGET_O_LARGEFILE 0 /* not necessary, always 64-bit */ +-#define TARGET_O_DIRECTORY 0100000 /* must be a directory */ +-#define TARGET_O_NOFOLLOW 0200000 /* don't follow links */ +-#define TARGET_O_DIRECT 02000000 /* direct disk access hint */ +-#define TARGET_O_NOATIME 04000000 +-#define TARGET_O_CLOEXEC 010000000 +-#define TARGET___O_SYNC 020000000 +-#define TARGET_O_PATH 040000000 +-#elif defined(TARGET_ARM) || defined(TARGET_M68K) +-#define TARGET_O_DIRECTORY 040000 /* must be a directory */ +-#define TARGET_O_NOFOLLOW 0100000 /* don't follow links */ +-#define TARGET_O_DIRECT 0200000 /* direct disk access hint */ +-#define TARGET_O_LARGEFILE 0400000 +-#elif defined(TARGET_MIPS) +-#define TARGET_O_APPEND 0x0008 +-#define TARGET_O_DSYNC 0x0010 +-#define TARGET_O_NONBLOCK 0x0080 +-#define TARGET_O_CREAT 0x0100 /* not fcntl */ +-#define TARGET_O_TRUNC 0x0200 /* not fcntl */ +-#define TARGET_O_EXCL 0x0400 /* not fcntl */ +-#define TARGET_O_NOCTTY 0x0800 /* not fcntl */ +-#define TARGET_FASYNC 0x1000 /* fcntl, for BSD compatibility */ +-#define TARGET_O_LARGEFILE 0x2000 /* allow large file opens */ +-#define TARGET___O_SYNC 0x4000 +-#define TARGET_O_DIRECT 0x8000 /* direct disk access hint */ +-#elif defined (TARGET_PPC) +-#define TARGET_O_DIRECTORY 040000 /* must be a directory */ +-#define TARGET_O_NOFOLLOW 0100000 /* don't follow links */ +-#define TARGET_O_LARGEFILE 0200000 +-#define TARGET_O_DIRECT 0400000 /* direct disk access hint */ +-#elif defined (TARGET_SPARC) +-#define TARGET_O_APPEND 0x0008 +-#define TARGET_FASYNC 0x0040 /* fcntl, for BSD compatibility */ +-#define TARGET_O_CREAT 0x0200 /* not fcntl */ +-#define TARGET_O_TRUNC 0x0400 /* not fcntl */ +-#define TARGET_O_EXCL 0x0800 /* not fcntl */ +-#define TARGET_O_DSYNC 0x2000 +-#define TARGET_O_NONBLOCK 0x4000 +-# ifdef TARGET_SPARC64 +-# define TARGET_O_NDELAY 0x0004 +-# else +-# define TARGET_O_NDELAY (0x0004 | TARGET_O_NONBLOCK) +-# endif +-#define TARGET_O_NOCTTY 0x8000 /* not fcntl */ +-#define TARGET_O_LARGEFILE 0x40000 +-#define TARGET_O_DIRECT 0x100000 /* direct disk access hint */ +-#define TARGET_O_NOATIME 0x200000 +-#define TARGET_O_CLOEXEC 0x400000 +-#define TARGET___O_SYNC 0x800000 +-#define TARGET_O_PATH 0x1000000 +-#endif +- +-/* values follow. */ +-#define TARGET_O_ACCMODE 0003 +-#define TARGET_O_RDONLY 00 +-#define TARGET_O_WRONLY 01 +-#define TARGET_O_RDWR 02 +-#ifndef TARGET_O_CREAT +-#define TARGET_O_CREAT 0100 /* not fcntl */ +-#endif +-#ifndef TARGET_O_EXCL +-#define TARGET_O_EXCL 0200 /* not fcntl */ +-#endif +-#ifndef TARGET_O_NOCTTY +-#define TARGET_O_NOCTTY 0400 /* not fcntl */ +-#endif +-#ifndef TARGET_O_TRUNC +-#define TARGET_O_TRUNC 01000 /* not fcntl */ +-#endif +-#ifndef TARGET_O_APPEND +-#define TARGET_O_APPEND 02000 +-#endif +-#ifndef TARGET_O_NONBLOCK +-#define TARGET_O_NONBLOCK 04000 +-#endif +-#ifndef TARGET_O_DSYNC +-#define TARGET_O_DSYNC 010000 +-#endif +-#ifndef TARGET_FASYNC +-#define TARGET_FASYNC 020000 /* fcntl, for BSD compatibility */ +-#endif +-#ifndef TARGET_O_DIRECT +-#define TARGET_O_DIRECT 040000 /* direct disk access hint */ +-#endif +-#ifndef TARGET_O_LARGEFILE +-#define TARGET_O_LARGEFILE 0100000 +-#endif +-#ifndef TARGET_O_DIRECTORY +-#define TARGET_O_DIRECTORY 0200000 /* must be a directory */ +-#endif +-#ifndef TARGET_O_NOFOLLOW +-#define TARGET_O_NOFOLLOW 0400000 /* don't follow links */ +-#endif +-#ifndef TARGET_O_NOATIME +-#define TARGET_O_NOATIME 01000000 +-#endif +-#ifndef TARGET_O_CLOEXEC +-#define TARGET_O_CLOEXEC 02000000 +-#endif +-#ifndef TARGET___O_SYNC +-#define TARGET___O_SYNC 04000000 +-#endif +-#ifndef TARGET_O_PATH +-#define TARGET_O_PATH 010000000 +-#endif +-#ifndef TARGET_O_NDELAY +-#define TARGET_O_NDELAY TARGET_O_NONBLOCK +-#endif +-#ifndef TARGET_O_SYNC +-#define TARGET_O_SYNC (TARGET___O_SYNC | TARGET_O_DSYNC) +-#endif +- +-struct target_flock { +- short l_type; +- short l_whence; +- abi_ulong l_start; +- abi_ulong l_len; +- int l_pid; +-}; +- +-struct target_flock64 { +- short l_type; +- short l_whence; +-#if defined(TARGET_PPC) || defined(TARGET_X86_64) || defined(TARGET_MIPS) || defined(TARGET_SPARC) || defined(TARGET_HPPA) || defined (TARGET_MICROBLAZE) +- int __pad; +-#endif +- unsigned long long l_start; +- unsigned long long l_len; +- int l_pid; +-} QEMU_PACKED; +- +-#ifdef TARGET_ARM +-struct target_eabi_flock64 { +- short l_type; +- short l_whence; +- int __pad; +- unsigned long long l_start; +- unsigned long long l_len; +- int l_pid; +-} QEMU_PACKED; +-#endif +- +-struct target_f_owner_ex { +- int type; /* Owner type of ID. */ +- int pid; /* ID of owner. */ +-}; +- +-/* soundcard defines */ +-/* XXX: convert them all to arch indepedent entries */ +-#define TARGET_SNDCTL_COPR_HALT TARGET_IOWR('C', 7, int); +-#define TARGET_SNDCTL_COPR_LOAD 0xcfb04301 +-#define TARGET_SNDCTL_COPR_RCODE 0xc0144303 +-#define TARGET_SNDCTL_COPR_RCVMSG 0x8fa44309 +-#define TARGET_SNDCTL_COPR_RDATA 0xc0144302 +-#define TARGET_SNDCTL_COPR_RESET 0x00004300 +-#define TARGET_SNDCTL_COPR_RUN 0xc0144306 +-#define TARGET_SNDCTL_COPR_SENDMSG 0xcfa44308 +-#define TARGET_SNDCTL_COPR_WCODE 0x40144305 +-#define TARGET_SNDCTL_COPR_WDATA 0x40144304 +-#define TARGET_SNDCTL_DSP_RESET TARGET_IO('P', 0) +-#define TARGET_SNDCTL_DSP_SYNC TARGET_IO('P', 1) +-#define TARGET_SNDCTL_DSP_SPEED TARGET_IOWR('P', 2, int) +-#define TARGET_SNDCTL_DSP_STEREO TARGET_IOWR('P', 3, int) +-#define TARGET_SNDCTL_DSP_GETBLKSIZE TARGET_IOWR('P', 4, int) +-#define TARGET_SNDCTL_DSP_SETFMT TARGET_IOWR('P', 5, int) +-#define TARGET_SNDCTL_DSP_CHANNELS TARGET_IOWR('P', 6, int) +-#define TARGET_SOUND_PCM_WRITE_FILTER TARGET_IOWR('P', 7, int) +-#define TARGET_SNDCTL_DSP_POST TARGET_IO('P', 8) +-#define TARGET_SNDCTL_DSP_SUBDIVIDE TARGET_IOWR('P', 9, int) +-#define TARGET_SNDCTL_DSP_SETFRAGMENT TARGET_IOWR('P',10, int) +-#define TARGET_SNDCTL_DSP_GETFMTS TARGET_IOR('P', 11, int) +-#define TARGET_SNDCTL_DSP_GETOSPACE TARGET_IORU('P',12) +-#define TARGET_SNDCTL_DSP_GETISPACE TARGET_IORU('P',13) +-#define TARGET_SNDCTL_DSP_GETCAPS TARGET_IOR('P', 15, int) +-#define TARGET_SNDCTL_DSP_GETTRIGGER TARGET_IOR('P',16, int) +-#define TARGET_SNDCTL_DSP_GETIPTR TARGET_IORU('P',17) +-#define TARGET_SNDCTL_DSP_GETOPTR TARGET_IORU('P',18) +-#define TARGET_SNDCTL_DSP_MAPINBUF TARGET_IORU('P', 19) +-#define TARGET_SNDCTL_DSP_MAPOUTBUF TARGET_IORU('P', 20) +-#define TARGET_SNDCTL_DSP_NONBLOCK 0x0000500e +-#define TARGET_SNDCTL_DSP_SAMPLESIZE 0xc0045005 +-#define TARGET_SNDCTL_DSP_SETDUPLEX 0x00005016 +-#define TARGET_SNDCTL_DSP_SETSYNCRO 0x00005015 +-#define TARGET_SNDCTL_DSP_SETTRIGGER 0x40045010 +-#define TARGET_SNDCTL_FM_4OP_ENABLE 0x4004510f +-#define TARGET_SNDCTL_FM_LOAD_INSTR 0x40285107 +-#define TARGET_SNDCTL_MIDI_INFO 0xc074510c +-#define TARGET_SNDCTL_MIDI_MPUCMD 0xc0216d02 +-#define TARGET_SNDCTL_MIDI_MPUMODE 0xc0046d01 +-#define TARGET_SNDCTL_MIDI_PRETIME 0xc0046d00 +-#define TARGET_SNDCTL_PMGR_ACCESS 0xcfb85110 +-#define TARGET_SNDCTL_PMGR_IFACE 0xcfb85001 +-#define TARGET_SNDCTL_SEQ_CTRLRATE 0xc0045103 +-#define TARGET_SNDCTL_SEQ_GETINCOUNT 0x80045105 +-#define TARGET_SNDCTL_SEQ_GETOUTCOUNT 0x80045104 +-#define TARGET_SNDCTL_SEQ_NRMIDIS 0x8004510b +-#define TARGET_SNDCTL_SEQ_NRSYNTHS 0x8004510a +-#define TARGET_SNDCTL_SEQ_OUTOFBAND 0x40085112 +-#define TARGET_SNDCTL_SEQ_PANIC 0x00005111 +-#define TARGET_SNDCTL_SEQ_PERCMODE 0x40045106 +-#define TARGET_SNDCTL_SEQ_RESET 0x00005100 +-#define TARGET_SNDCTL_SEQ_RESETSAMPLES 0x40045109 +-#define TARGET_SNDCTL_SEQ_SYNC 0x00005101 +-#define TARGET_SNDCTL_SEQ_TESTMIDI 0x40045108 +-#define TARGET_SNDCTL_SEQ_THRESHOLD 0x4004510d +-#define TARGET_SNDCTL_SEQ_TRESHOLD 0x4004510d +-#define TARGET_SNDCTL_SYNTH_INFO 0xc08c5102 +-#define TARGET_SNDCTL_SYNTH_MEMAVL 0xc004510e +-#define TARGET_SNDCTL_TMR_CONTINUE 0x00005404 +-#define TARGET_SNDCTL_TMR_METRONOME 0x40045407 +-#define TARGET_SNDCTL_TMR_SELECT 0x40045408 +-#define TARGET_SNDCTL_TMR_SOURCE 0xc0045406 +-#define TARGET_SNDCTL_TMR_START 0x00005402 +-#define TARGET_SNDCTL_TMR_STOP 0x00005403 +-#define TARGET_SNDCTL_TMR_TEMPO 0xc0045405 +-#define TARGET_SNDCTL_TMR_TIMEBASE 0xc0045401 +-#define TARGET_SOUND_PCM_READ_RATE 0x80045002 +-#define TARGET_SOUND_PCM_READ_CHANNELS 0x80045006 +-#define TARGET_SOUND_PCM_READ_BITS 0x80045005 +-#define TARGET_SOUND_PCM_READ_FILTER 0x80045007 +-#define TARGET_SOUND_MIXER_INFO TARGET_IOR ('M', 101, mixer_info) +-#define TARGET_SOUND_MIXER_ACCESS 0xc0804d66 +-#define TARGET_SOUND_MIXER_PRIVATE1 TARGET_IOWR('M', 111, int) +-#define TARGET_SOUND_MIXER_PRIVATE2 TARGET_IOWR('M', 112, int) +-#define TARGET_SOUND_MIXER_PRIVATE3 TARGET_IOWR('M', 113, int) +-#define TARGET_SOUND_MIXER_PRIVATE4 TARGET_IOWR('M', 114, int) +-#define TARGET_SOUND_MIXER_PRIVATE5 TARGET_IOWR('M', 115, int) +- +-#define TARGET_MIXER_READ(dev) TARGET_IOR('M', dev, int) +- +-#define TARGET_SOUND_MIXER_READ_VOLUME TARGET_MIXER_READ(SOUND_MIXER_VOLUME) +-#define TARGET_SOUND_MIXER_READ_BASS TARGET_MIXER_READ(SOUND_MIXER_BASS) +-#define TARGET_SOUND_MIXER_READ_TREBLE TARGET_MIXER_READ(SOUND_MIXER_TREBLE) +-#define TARGET_SOUND_MIXER_READ_SYNTH TARGET_MIXER_READ(SOUND_MIXER_SYNTH) +-#define TARGET_SOUND_MIXER_READ_PCM TARGET_MIXER_READ(SOUND_MIXER_PCM) +-#define TARGET_SOUND_MIXER_READ_SPEAKER TARGET_MIXER_READ(SOUND_MIXER_SPEAKER) +-#define TARGET_SOUND_MIXER_READ_LINE TARGET_MIXER_READ(SOUND_MIXER_LINE) +-#define TARGET_SOUND_MIXER_READ_MIC TARGET_MIXER_READ(SOUND_MIXER_MIC) +-#define TARGET_SOUND_MIXER_READ_CD TARGET_MIXER_READ(SOUND_MIXER_CD) +-#define TARGET_SOUND_MIXER_READ_IMIX TARGET_MIXER_READ(SOUND_MIXER_IMIX) +-#define TARGET_SOUND_MIXER_READ_ALTPCM TARGET_MIXER_READ(SOUND_MIXER_ALTPCM) +-#define TARGET_SOUND_MIXER_READ_RECLEV TARGET_MIXER_READ(SOUND_MIXER_RECLEV) +-#define TARGET_SOUND_MIXER_READ_IGAIN TARGET_MIXER_READ(SOUND_MIXER_IGAIN) +-#define TARGET_SOUND_MIXER_READ_OGAIN TARGET_MIXER_READ(SOUND_MIXER_OGAIN) +-#define TARGET_SOUND_MIXER_READ_LINE1 TARGET_MIXER_READ(SOUND_MIXER_LINE1) +-#define TARGET_SOUND_MIXER_READ_LINE2 TARGET_MIXER_READ(SOUND_MIXER_LINE2) +-#define TARGET_SOUND_MIXER_READ_LINE3 TARGET_MIXER_READ(SOUND_MIXER_LINE3) +- +-/* Obsolete macros */ +-#define TARGET_SOUND_MIXER_READ_MUTE TARGET_MIXER_READ(SOUND_MIXER_MUTE) +-#define TARGET_SOUND_MIXER_READ_ENHANCE TARGET_MIXER_READ(SOUND_MIXER_ENHANCE) +-#define TARGET_SOUND_MIXER_READ_LOUD TARGET_MIXER_READ(SOUND_MIXER_LOUD) +- +-#define TARGET_SOUND_MIXER_READ_RECSRC TARGET_MIXER_READ(SOUND_MIXER_RECSRC) +-#define TARGET_SOUND_MIXER_READ_DEVMASK TARGET_MIXER_READ(SOUND_MIXER_DEVMASK) +-#define TARGET_SOUND_MIXER_READ_RECMASK TARGET_MIXER_READ(SOUND_MIXER_RECMASK) +-#define TARGET_SOUND_MIXER_READ_STEREODEVS TARGET_MIXER_READ(SOUND_MIXER_STEREODEVS) +-#define TARGET_SOUND_MIXER_READ_CAPS TARGET_MIXER_READ(SOUND_MIXER_CAPS) +- +-#define TARGET_MIXER_WRITE(dev) TARGET_IOWR('M', dev, int) +- +-#define TARGET_SOUND_MIXER_WRITE_VOLUME TARGET_MIXER_WRITE(SOUND_MIXER_VOLUME) +-#define TARGET_SOUND_MIXER_WRITE_BASS TARGET_MIXER_WRITE(SOUND_MIXER_BASS) +-#define TARGET_SOUND_MIXER_WRITE_TREBLE TARGET_MIXER_WRITE(SOUND_MIXER_TREBLE) +-#define TARGET_SOUND_MIXER_WRITE_SYNTH TARGET_MIXER_WRITE(SOUND_MIXER_SYNTH) +-#define TARGET_SOUND_MIXER_WRITE_PCM TARGET_MIXER_WRITE(SOUND_MIXER_PCM) +-#define TARGET_SOUND_MIXER_WRITE_SPEAKER TARGET_MIXER_WRITE(SOUND_MIXER_SPEAKER) +-#define TARGET_SOUND_MIXER_WRITE_LINE TARGET_MIXER_WRITE(SOUND_MIXER_LINE) +-#define TARGET_SOUND_MIXER_WRITE_MIC TARGET_MIXER_WRITE(SOUND_MIXER_MIC) +-#define TARGET_SOUND_MIXER_WRITE_CD TARGET_MIXER_WRITE(SOUND_MIXER_CD) +-#define TARGET_SOUND_MIXER_WRITE_IMIX TARGET_MIXER_WRITE(SOUND_MIXER_IMIX) +-#define TARGET_SOUND_MIXER_WRITE_ALTPCM TARGET_MIXER_WRITE(SOUND_MIXER_ALTPCM) +-#define TARGET_SOUND_MIXER_WRITE_RECLEV TARGET_MIXER_WRITE(SOUND_MIXER_RECLEV) +-#define TARGET_SOUND_MIXER_WRITE_IGAIN TARGET_MIXER_WRITE(SOUND_MIXER_IGAIN) +-#define TARGET_SOUND_MIXER_WRITE_OGAIN TARGET_MIXER_WRITE(SOUND_MIXER_OGAIN) +-#define TARGET_SOUND_MIXER_WRITE_LINE1 TARGET_MIXER_WRITE(SOUND_MIXER_LINE1) +-#define TARGET_SOUND_MIXER_WRITE_LINE2 TARGET_MIXER_WRITE(SOUND_MIXER_LINE2) +-#define TARGET_SOUND_MIXER_WRITE_LINE3 TARGET_MIXER_WRITE(SOUND_MIXER_LINE3) +- +-/* Obsolete macros */ +-#define TARGET_SOUND_MIXER_WRITE_MUTE TARGET_MIXER_WRITE(SOUND_MIXER_MUTE) +-#define TARGET_SOUND_MIXER_WRITE_ENHANCE TARGET_MIXER_WRITE(SOUND_MIXER_ENHANCE) +-#define TARGET_SOUND_MIXER_WRITE_LOUD TARGET_MIXER_WRITE(SOUND_MIXER_LOUD) +- +-#define TARGET_SOUND_MIXER_WRITE_RECSRC TARGET_MIXER_WRITE(SOUND_MIXER_RECSRC) +- +-/* vfat ioctls */ +-#define TARGET_VFAT_IOCTL_READDIR_BOTH TARGET_IORU('r', 1) +-#define TARGET_VFAT_IOCTL_READDIR_SHORT TARGET_IORU('r', 2) +- +-#define TARGET_MTIOCTOP TARGET_IOW('m', 1, struct mtop) +-#define TARGET_MTIOCGET TARGET_IOR('m', 2, struct mtget) +-#define TARGET_MTIOCPOS TARGET_IOR('m', 3, struct mtpos) +- +-struct target_sysinfo { +- abi_long uptime; /* Seconds since boot */ +- abi_ulong loads[3]; /* 1, 5, and 15 minute load averages */ +- abi_ulong totalram; /* Total usable main memory size */ +- abi_ulong freeram; /* Available memory size */ +- abi_ulong sharedram; /* Amount of shared memory */ +- abi_ulong bufferram; /* Memory used by buffers */ +- abi_ulong totalswap; /* Total swap space size */ +- abi_ulong freeswap; /* swap space still available */ +- unsigned short procs; /* Number of current processes */ +- unsigned short pad; /* explicit padding for m68k */ +- abi_ulong totalhigh; /* Total high memory size */ +- abi_ulong freehigh; /* Available high memory size */ +- unsigned int mem_unit; /* Memory unit size in bytes */ +- char _f[20-2*sizeof(abi_long)-sizeof(int)]; /* Padding: libc5 uses this.. */ +-}; +- +-struct linux_dirent { +- long d_ino; +- unsigned long d_off; +- unsigned short d_reclen; +- char d_name[256]; /* We must not include limits.h! */ +-}; +- +-struct linux_dirent64 { +- uint64_t d_ino; +- int64_t d_off; +- unsigned short d_reclen; +- unsigned char d_type; +- char d_name[256]; +-}; +- +-struct target_mq_attr { +- abi_long mq_flags; +- abi_long mq_maxmsg; +- abi_long mq_msgsize; +- abi_long mq_curmsgs; +-}; +- +-#include "socket.h" + + #include "errno_defs.h" + +-#define FUTEX_WAIT 0 +-#define FUTEX_WAKE 1 +-#define FUTEX_FD 2 +-#define FUTEX_REQUEUE 3 +-#define FUTEX_CMP_REQUEUE 4 +-#define FUTEX_WAKE_OP 5 +-#define FUTEX_LOCK_PI 6 +-#define FUTEX_UNLOCK_PI 7 +-#define FUTEX_TRYLOCK_PI 8 +-#define FUTEX_WAIT_BITSET 9 +-#define FUTEX_WAKE_BITSET 10 +- +-#define FUTEX_PRIVATE_FLAG 128 +-#define FUTEX_CLOCK_REALTIME 256 +-#define FUTEX_CMD_MASK ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME) +- +-#ifdef CONFIG_EPOLL +-typedef union target_epoll_data { +- abi_ulong ptr; +- abi_ulong fd; +- uint32_t u32; +- uint64_t u64; +-} target_epoll_data_t; +- +-struct target_epoll_event { +- uint32_t events; +-#if defined(TARGET_ARM) || defined(TARGET_MIPS) || defined(TARGET_MIPS64) +- uint32_t __pad; +-#endif +- target_epoll_data_t data; +-} QEMU_PACKED; +-#endif +-struct target_rlimit64 { +- uint64_t rlim_cur; +- uint64_t rlim_max; +-}; +- +-struct target_ucred { +- uint32_t pid; +- uint32_t uid; +- uint32_t gid; +-}; +- +-#endif +- +-typedef int32_t target_timer_t; +- +-#define TARGET_SIGEV_MAX_SIZE 64 +- +-/* This is architecture-specific but most architectures use the default */ +-#ifdef TARGET_MIPS +-#define TARGET_SIGEV_PREAMBLE_SIZE (sizeof(int32_t) * 2 + sizeof(abi_long)) +-#else +-#define TARGET_SIGEV_PREAMBLE_SIZE (sizeof(int32_t) * 2 \ +- + sizeof(target_sigval_t)) + #endif +- +-#define TARGET_SIGEV_PAD_SIZE ((TARGET_SIGEV_MAX_SIZE \ +- - TARGET_SIGEV_PREAMBLE_SIZE) \ +- / sizeof(int32_t)) +- +-struct target_sigevent { +- target_sigval_t sigev_value; +- int32_t sigev_signo; +- int32_t sigev_notify; +- union { +- int32_t _pad[TARGET_SIGEV_PAD_SIZE]; +- int32_t _tid; +- +- struct { +- void (*_function)(sigval_t); +- void *_attribute; +- } _sigev_thread; +- } _sigev_un; +-}; +- +-struct target_user_cap_header { +- uint32_t version; +- int pid; +-}; +- +-struct target_user_cap_data { +- uint32_t effective; +- uint32_t permitted; +- uint32_t inheritable; +-}; +diff --git a/home/gkrishna/Shelly/work/qemu/qapi/string-input-visitor.c b/home/gkrishna/Shelly/work/qemu-cgc/qapi/string-input-visitor.c +index d8a8db0..e2723ee 100644 +--- a/home/gkrishna/Shelly/work/qemu/qapi/string-input-visitor.c ++++ b/home/gkrishna/Shelly/work/qemu-cgc/qapi/string-input-visitor.c +@@ -289,7 +289,11 @@ static void parse_type_number(Visitor *v, double *obj, const char *name, + errno = 0; + if (siv->string) { + val = strtod(siv->string, &endp); ++ } else { ++ fprintf(stderr, "qemu: The compiler complains if I don't check... and it was right!\n"); ++ exit(-38); + } ++ + if (!siv->string || errno || endp == siv->string || *endp) { + error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null", + "number"); +diff --git a/home/gkrishna/Shelly/work/qemu/qemu-log.c b/home/gkrishna/Shelly/work/qemu-cgc/qemu-log.c +index 13f3813..4339518 100644 +--- a/home/gkrishna/Shelly/work/qemu/qemu-log.c ++++ b/home/gkrishna/Shelly/work/qemu-cgc/qemu-log.c +@@ -20,10 +20,14 @@ + #include "qemu-common.h" + #include "qemu/log.h" + ++#define MAX_LOG_ENTRIES 100 ++#define CIRCULAR_BUFFER_SPLIT "==========SPLIT==========\n" ++ + static char *logfilename; + FILE *qemu_logfile; + int qemu_loglevel; + static int log_append = 0; ++static unsigned int current_entry = 0; + + void qemu_log(const char *fmt, ...) + { +@@ -32,6 +36,17 @@ void qemu_log(const char *fmt, ...) + va_start(ap, fmt); + if (qemu_logfile) { + vfprintf(qemu_logfile, fmt, ap); ++ ++ if (qemu_loglevel_mask(LOG_CIRCULAR_BUFFER)){ ++ current_entry++; ++ if(current_entry > MAX_LOG_ENTRIES){ ++ current_entry = 0; ++ ftruncate(fileno(qemu_logfile),(off_t)ftell(qemu_logfile)); ++ fseek(qemu_logfile, 0, SEEK_SET); ++ } ++ fprintf(qemu_logfile, CIRCULAR_BUFFER_SPLIT); ++ fseek(qemu_logfile, -1*sizeof(CIRCULAR_BUFFER_SPLIT)+1, SEEK_CUR); ++ } + } + va_end(ap); + } +@@ -91,6 +106,8 @@ void qemu_set_log_filename(const char *filename) + } + + const QEMULogItem qemu_log_items[] = { ++ { LOG_CIRCULAR_BUFFER, "circular", ++ "log in a circular buffer" }, + { CPU_LOG_TB_OUT_ASM, "out_asm", + "show generated host assembly code for each compiled TB" }, + { CPU_LOG_TB_IN_ASM, "in_asm", +diff --git a/home/gkrishna/Shelly/work/qemu-cgc/roms/seabios/.gitignore b/home/gkrishna/Shelly/work/qemu-cgc/roms/seabios/.gitignore +new file mode 100644 +index 0000000..58378e9 +--- /dev/null ++++ b/home/gkrishna/Shelly/work/qemu-cgc/roms/seabios/.gitignore +@@ -0,0 +1 @@ ++/config.mak +diff --git a/home/gkrishna/Shelly/work/qemu-cgc/roms/vgabios/.gitignore b/home/gkrishna/Shelly/work/qemu-cgc/roms/vgabios/.gitignore +new file mode 100644 +index 0000000..58378e9 +--- /dev/null ++++ b/home/gkrishna/Shelly/work/qemu-cgc/roms/vgabios/.gitignore +@@ -0,0 +1 @@ ++/config.mak +diff --git a/home/gkrishna/Shelly/work/qemu/target-i386/translate.c b/home/gkrishna/Shelly/work/qemu-cgc/target-i386/translate.c +index 305ce50..53fa88a 100644 +--- a/home/gkrishna/Shelly/work/qemu/target-i386/translate.c ++++ b/home/gkrishna/Shelly/work/qemu-cgc/target-i386/translate.c +@@ -8086,7 +8086,7 @@ done_generating: + if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { + int disas_flags; + qemu_log("----------------\n"); +- qemu_log("IN: %s\n", lookup_symbol(pc_start)); ++ qemu_log("IN: %s [%08x,%08x]\n", lookup_symbol(pc_start),pc_start,pc_ptr - pc_start); + #ifdef TARGET_X86_64 + if (dc->code64) + disas_flags = 2; +diff --git a/home/gkrishna/Shelly/work/qemu/tests/tcg/test-i386.c b/home/gkrishna/Shelly/work/qemu-cgc/tests/tcg/test-i386.c +index b05572b..dd522cf 100644 +--- a/home/gkrishna/Shelly/work/qemu/tests/tcg/test-i386.c ++++ b/home/gkrishna/Shelly/work/qemu-cgc/tests/tcg/test-i386.c +@@ -1720,7 +1720,7 @@ int tab[2]; + + void sig_handler(int sig, siginfo_t *info, void *puc) + { +- struct ucontext *uc = puc; ++ ucontext_t *uc = puc; + + printf("si_signo=%d si_errno=%d si_code=%d", + info->si_signo, info->si_errno, info->si_code); +@@ -1912,7 +1912,7 @@ void test_exceptions(void) + /* specific precise single step test */ + void sig_trap_handler(int sig, siginfo_t *info, void *puc) + { +- struct ucontext *uc = puc; ++ ucontext_t *uc = puc; + printf("EIP=" FMTLX "\n", (long)uc->uc_mcontext.gregs[REG_EIP]); + } + +diff --git a/home/gkrishna/Shelly/work/qemu-cgc/tracer-config b/home/gkrishna/Shelly/work/qemu-cgc/tracer-config +new file mode 100755 +index 0000000..4121264 +--- /dev/null ++++ b/home/gkrishna/Shelly/work/qemu-cgc/tracer-config +@@ -0,0 +1,3 @@ ++#!/bin/sh ++ ++./cgc_configure_tracer_opt +diff --git a/home/gkrishna/Shelly/work/qemu/translate-all.c b/home/gkrishna/Shelly/work/qemu-cgc/translate-all.c +index 11763c6..1877739 100644 +--- a/home/gkrishna/Shelly/work/qemu/translate-all.c ++++ b/home/gkrishna/Shelly/work/qemu-cgc/translate-all.c +@@ -115,9 +115,10 @@ typedef struct PageDesc { + + #define V_L1_SHIFT (L1_MAP_ADDR_SPACE_BITS - TARGET_PAGE_BITS - V_L1_BITS) + +-uintptr_t qemu_real_host_page_size; +-uintptr_t qemu_host_page_size; +-uintptr_t qemu_host_page_mask; ++// TURNED INTO CONSTANTS FOR CGC [J] ++//uintptr_t qemu_real_host_page_size; ++//uintptr_t qemu_host_page_size; ++//uintptr_t qemu_host_page_mask; + + /* This is a multi-level map on the virtual address space. + The bottom level has pointers to PageDesc. */ +@@ -302,16 +303,12 @@ static __attribute__((unused)) void map_exec(void *addr, long size) + + void page_size_init(void) + { +- /* NOTE: we can always suppose that qemu_host_page_size >= +- TARGET_PAGE_SIZE */ +- qemu_real_host_page_size = getpagesize(); +- if (qemu_host_page_size == 0) { +- qemu_host_page_size = qemu_real_host_page_size; +- } +- if (qemu_host_page_size < TARGET_PAGE_SIZE) { +- qemu_host_page_size = TARGET_PAGE_SIZE; +- } +- qemu_host_page_mask = ~(qemu_host_page_size - 1); ++ // TURNED INTO CONSTANTS FOR CGC [J] ++ assert(qemu_real_host_page_size == getpagesize()); ++ assert(qemu_host_page_size == getpagesize()); ++ assert(qemu_host_page_size == TARGET_PAGE_SIZE); ++ assert(qemu_host_page_size == 4096); ++ assert(qemu_host_page_mask == (~(qemu_host_page_size - 1))); + } + + static void page_init(void) +@@ -391,10 +388,16 @@ static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc) + + #if defined(CONFIG_USER_ONLY) + /* We can't use g_malloc because it may recurse into a locked mutex. */ ++ /* (Note: error-checking courtesy of AFL */ + # define ALLOC(P, SIZE) \ + do { \ +- P = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, \ ++ void *_tmp = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, \ + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); \ ++ if (_tmp == (void*)-1) { \ ++ qemu_log(">>> Out of memory for stack, bailing out. <<<\n"); \ ++ exit(1); \ ++ } \ ++ (P) = _tmp; \ + } while (0) + #else + # define ALLOC(P, SIZE) \ +@@ -821,7 +824,7 @@ static void tb_invalidate_check(target_ulong address) + + address &= TARGET_PAGE_MASK; + for (i = 0; i < CODE_GEN_PHYS_HASH_SIZE; i++) { +- for (tb = tb_ctx.tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) { ++ for (tb = tcg_ctx.tb_ctx.tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) { + if (!(address + TARGET_PAGE_SIZE <= tb->pc || + address >= tb->pc + tb->size)) { + printf("ERROR invalidate: address=" TARGET_FMT_lx +@@ -1327,6 +1330,7 @@ static inline void tb_alloc_page(TranslationBlock *tb, + + tb->page_addr[n] = page_addr; + p = page_find_alloc(page_addr >> TARGET_PAGE_BITS, 1); ++ + tb->page_next[n] = p->first_tb; + #ifndef CONFIG_USER_ONLY + page_already_protected = p->first_tb != NULL; +@@ -1335,6 +1339,26 @@ static inline void tb_alloc_page(TranslationBlock *tb, + invalidate_page_bitmap(p); + + #if defined(CONFIG_USER_ONLY) ++ ++#ifdef ENFORCE_NX ++ { ++ // ADDED: NX check ++ // Not sure this covers all, but should be good enough for CGC [J] ++ // (In particular, may want to go to tb_gen_code, or possibly even find_slow) ++ target_ulong addr; ++ PageDesc *p2; ++ tb_page_addr_t pa = page_addr; ++ pa &= qemu_host_page_mask; ++ for (addr = pa; addr < pa + qemu_host_page_size; ++ addr += TARGET_PAGE_SIZE) { ++ p2 = page_find(addr >> TARGET_PAGE_BITS); ++ if ((p2->flags & PAGE_EXEC) == 0) { ++ fprintf(stderr, "OUR CGC QEMU: NX enforcement! tried tb_alloc_page on page %#x (first page = %#x)\n", addr, page_addr); ++ exit(46); // TODO: what to do? cpu_abort? ++ } ++ } ++ } ++#endif + if (p->flags & PAGE_WRITE) { + target_ulong addr; + PageDesc *p2; +@@ -1878,6 +1902,120 @@ int page_check_range(target_ulong start, target_ulong len, int flags) + } + return 0; + } ++/* "BUG": receive()/transmit()/... (like read()/write()/...) check ++ * permissions only on actual access, return short lengths ++ * if at least some succeeded. ++ * In other words, pizza's transmit(len=0x11223344) should ++ * succeed, and send only up to the process can access. ++ * ++ * FOR CGC: A quick fix is to "adjust" the lengths to match the max ++ * possible, before an actual read()/write() ++ * TODO: Could be done better by delegating to host page permissions ++ * (should be possible, we're x86 with a 64-bit address space) ++ * Also, this is quite tricky. Might want to check again. */ ++ ++/* Mostly, valid_len is a copy of page_check_range, but returns: ++ * ++ * > 0 Number of bytes that satisfy the condition. ++ * Cannot be more than 31-bit, but should not be a problem :D ++ * ++ * 0 Only if (len == 0), kept for compat. ++ * ++ * -1 is still an error. ++ */ ++target_long valid_len(target_ulong start, target_ulong len, int flags) ++{ ++ PageDesc *p; ++ target_ulong end; ++ target_ulong addr; ++ ++ /* This function should never be called with addresses outside the ++ guest address space. If this assert fires, it probably indicates ++ a missing call to h2g_valid. */ ++#if TARGET_ABI_BITS > L1_MAP_ADDR_SPACE_BITS ++ assert(start < ((target_ulong)1 << L1_MAP_ADDR_SPACE_BITS)); ++#endif ++ ++ if (len == 0) { ++ return 0; ++ } ++ if (start + len - 1 < start) { ++ /* We've wrapped around. */ ++ return -1; ++ } ++ ++ _Static_assert(TARGET_LONG_SIZE == 4, "CGC is 32-bit only!"); ++ int ok_pages = 0; ++ const target_ulong req_start = start, req_len = len; ++ ++ /* must do before we loose bits in the next step */ ++ end = TARGET_PAGE_ALIGN(start + len); ++ start = start & TARGET_PAGE_MASK; ++ ++ for (addr = start, len = end - start; ++ len != 0; ++ len -= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) { ++ p = page_find(addr >> TARGET_PAGE_BITS); ++ if (!p) { ++ goto retlen; ++ } ++ if (!(p->flags & PAGE_VALID)) { ++ goto retlen; ++ } ++ ++ if ((flags & PAGE_READ) && !(p->flags & PAGE_READ)) { ++ goto retlen; ++ } ++ if (flags & PAGE_WRITE) { ++ if (!(p->flags & PAGE_WRITE_ORG)) { ++ goto retlen; ++ } ++ /* unprotect the page if it was put read-only because it ++ contains translated code */ ++ if (!(p->flags & PAGE_WRITE)) { ++ if (!page_unprotect(addr, 0, NULL)) { ++ goto retlen; ++ } ++ } ++ } ++ ok_pages++; ++ } ++retlen: ++ if (ok_pages == 0) ++ return -1; /* No valid pages -> error */ ++ ++ /* (Page-aligned) byte count */ ++ target_ulong ret = ok_pages * TARGET_PAGE_SIZE; ++ ++ /* Remove what was added to page-align the start... */ ++ assert(start <= req_start); ++ ret -= (req_start - start); ++ /* ... and the end */ ++ ++ /* Using `end` here for the calculation can lead to problems when the page-aligned ++ * `end` variable does not proceed a mapped page, instead we should use the value ++ * of start + (ok_pages * TARGET_PAGE_SIZE) to get the boundary of the region. */ ++ const target_ulong real_end = start + (ok_pages * TARGET_PAGE_SIZE); ++ const target_ulong req_end = req_start + req_len; ++ /* So cases do exist where the end of the region is LESS than the requested end. ++ * Only in cases where the real_end is is greater than the requested end should ++ * be subtraction be done. */ ++ if (real_end > req_end) ++ ret -= (real_end - req_end); ++ ++ if (ret > req_len) { ++ fprintf(stderr, "OUR QEMU/CGC ERROR: valid_len should only shorten byte counts, not make them larger! (" TARGET_FMT_lu " > " TARGET_FMT_lu ")\n", ret, req_len); ++ exit(-90); ++ } ++ ++ if (ret > INT32_MAX) { ++ /* Not actually possible, right? */ ++ fprintf(stderr, "OUR QEMU/CGC WARNING: More than 2 GB of valid space? Should not be possible in CGC, so I further short the length. (" TARGET_FMT_lu " bytes had page permissions OK, returning INT32_MAX instead).\n", ret); ++ return INT32_MAX; ++ } ++ return (target_long) ret; ++} ++ + + /* called from signal handler: invalidate the code and unprotect the + page. Return TRUE if the fault was successfully handled. */ +diff --git a/home/gkrishna/Shelly/work/qemu/user-exec.c b/home/gkrishna/Shelly/work/qemu-cgc/user-exec.c +index 8f57e8a..957f9f7 100644 +--- a/home/gkrishna/Shelly/work/qemu/user-exec.c ++++ b/home/gkrishna/Shelly/work/qemu-cgc/user-exec.c +@@ -57,7 +57,7 @@ static void exception_action(CPUState *cpu) + void cpu_resume_from_signal(CPUState *cpu, void *puc) + { + #ifdef __linux__ +- struct ucontext *uc = puc; ++ ucontext_t *uc = puc; + #elif defined(__OpenBSD__) + struct sigcontext *uc = puc; + #endif +@@ -171,7 +171,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, + #elif defined(__OpenBSD__) + struct sigcontext *uc = puc; + #else +- struct ucontext *uc = puc; ++ ucontext_t *uc = puc; + #endif + unsigned long pc; + int trapno; +@@ -226,7 +226,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, + #elif defined(__OpenBSD__) + struct sigcontext *uc = puc; + #else +- struct ucontext *uc = puc; ++ ucontext_t *uc = puc; + #endif + + pc = PC_sig(uc); +@@ -288,7 +288,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, + + #ifdef __APPLE__ + #include +-typedef struct ucontext SIGCONTEXT; ++typedef ucontext_t SIGCONTEXT; + /* All Registers access - only for local access */ + #define REG_sig(reg_name, context) \ + ((context)->uc_mcontext->ss.reg_name) +@@ -331,7 +331,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, + #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + ucontext_t *uc = puc; + #else +- struct ucontext *uc = puc; ++ ucontext_t *uc = puc; + #endif + unsigned long pc; + int is_write; +@@ -358,7 +358,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, + void *puc) + { + siginfo_t *info = pinfo; +- struct ucontext *uc = puc; ++ ucontext_t *uc = puc; + uint32_t *pc = uc->uc_mcontext.sc_pc; + uint32_t insn = *pc; + int is_write = 0; +@@ -456,7 +456,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, + #if defined(__NetBSD__) + ucontext_t *uc = puc; + #else +- struct ucontext *uc = puc; ++ ucontext_t *uc = puc; + #endif + unsigned long pc; + int is_write; +@@ -483,7 +483,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, + int cpu_signal_handler(int host_signum, void *pinfo, void *puc) + { + siginfo_t *info = pinfo; +- struct ucontext *uc = puc; ++ ucontext_t *uc = puc; + uintptr_t pc = uc->uc_mcontext.pc; + uint32_t insn = *(uint32_t *)pc; + bool is_write; +@@ -512,7 +512,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, + void *puc) + { + siginfo_t *info = pinfo; +- struct ucontext *uc = puc; ++ ucontext_t *uc = puc; + unsigned long pc; + int is_write; + +@@ -534,7 +534,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, + int cpu_signal_handler(int host_signum, void *pinfo, void *puc) + { + siginfo_t *info = pinfo; +- struct ucontext *uc = puc; ++ ucontext_t *uc = puc; + unsigned long ip; + int is_write = 0; + +@@ -565,7 +565,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, + void *puc) + { + siginfo_t *info = pinfo; +- struct ucontext *uc = puc; ++ ucontext_t *uc = puc; + unsigned long pc; + uint16_t *pinsn; + int is_write = 0; +@@ -618,7 +618,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, + void *puc) + { + siginfo_t *info = pinfo; +- struct ucontext *uc = puc; ++ ucontext_t *uc = puc; + greg_t pc = uc->uc_mcontext.pc; + int is_write; + +@@ -634,7 +634,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, + void *puc) + { + siginfo_t *info = pinfo; +- struct ucontext *uc = puc; ++ ucontext_t *uc = puc; + unsigned long pc = uc->uc_mcontext.sc_iaoq[0]; + uint32_t insn = *(uint32_t *)pc; + int is_write = 0; diff --git a/setup.py b/setup.py index d837848..9704162 100644 --- a/setup.py +++ b/setup.py @@ -18,6 +18,7 @@ QEMU_REPO_PATH_LINUX = "shellphish-qemu-linux" QEMU_LINUX_TRACER_PATCH = os.path.join("..", "patches", "tracer-qemu.patch") QEMU_LINUX_UPDATE_PATCH = os.path.join("..", "patches", "ucontext.patch") +QEMU_LINUX_CGC_PATCH = os.path.join("..", "patches", "version.patch") QEMU_PATH_CGC_TRACER = os.path.join(BIN_PATH, "shellphish-qemu-cgc-tracer") QEMU_PATH_CGC_NXTRACER = os.path.join(BIN_PATH, "shellphish-qemu-cgc-nxtracer") @@ -33,6 +34,8 @@ QEMU_PATH_LINUX_ARM = os.path.join(BIN_PATH, "shellphish-qemu-linux-arm") QEMU_PATH_LINUX_AARCH64 = os.path.join(BIN_PATH, "shellphish-qemu-linux-aarch64") +TRACER_QEMU_REPO_LINUX = "https://github.com/qemu/qemu.git" + ALL_QEMU_BINS = [ QEMU_PATH_CGC_BASE, QEMU_PATH_CGC_TRACER, @@ -48,133 +51,119 @@ QEMU_PATH_LINUX_AARCH64, ] -def _clone_cgc_qemu(): - # grab the CGC repo - if not os.path.exists(QEMU_REPO_PATH_CGC_BASE) \ - or not os.path.exists(QEMU_REPO_PATH_CGC_BASE): - TRACER_QEMU_REPO_CGC = "https://github.com/mechaphish/qemu-cgc" - # since we're cloning from gitlab we'll need to try a couple times, since gitlab - # has a cap on the number of ssh workers - retrieved = False - - for _ in range(10): - if subprocess.call(['git', 'clone', '--branch', 'base_cgc', '--depth=1', TRACER_QEMU_REPO_CGC, QEMU_REPO_PATH_CGC_BASE]) == 0: - retrieved = True - break - else: - time.sleep(random.randint(0, 10)) - - if not retrieved: - raise LibError("Unable to retrieve tracer qemu") - - # update tracer qemu for cgc - if subprocess.call(['git', 'pull'], cwd=QEMU_REPO_PATH_CGC_BASE) != 0: - raise LibError("Unable to retrieve cgc base qemu") - def _clone_linux_qemu(): # grab the linux tarball if not os.path.exists(QEMU_REPO_PATH_LINUX): - TRACER_QEMU_REPO_LINUX = "https://github.com/qemu/qemu.git" if subprocess.call(['git', 'clone', '--branch', 'v2.3.0', '--depth=1', TRACER_QEMU_REPO_LINUX, QEMU_REPO_PATH_LINUX]) != 0: raise LibError("Unable to retrieve qemu repository \"%s\"" % TRACER_QEMU_REPO_LINUX) - #if subprocess.call(['git', '-C', QEMU_REPO_PATH_LINUX, 'checkout', 'tags/v2.3.0']) != 0: - # raise LibError("Unable to checkout version 2.3.0 of qemu") if subprocess.call(['git', '-C', QEMU_REPO_PATH_LINUX, 'apply', QEMU_LINUX_TRACER_PATCH]) != 0: raise LibError("Unable to apply tracer patch to qemu") if subprocess.call(['git', '-C', QEMU_REPO_PATH_LINUX, 'apply', QEMU_LINUX_UPDATE_PATCH]) != 0: raise LibError("Unable to apply ucontext_t update patch to qemu") + _build_standard_qemu() -def _build_qemus(): + +def _build_standard_qemu(): if not os.path.exists(BIN_PATH): try: os.makedirs(BIN_PATH) except OSError: raise LibError("Unable to create bin directory") + print("Folder created") + print("Configuring Linux qemu...") + if subprocess.call(['./tracer-config'], cwd=QEMU_REPO_PATH_LINUX) != 0: + raise LibError("Unable to configure shellphish-qemu-linux") + print("Building Linux qemu...") + if subprocess.call(['make', '-j4'], cwd=QEMU_REPO_PATH_LINUX) != 0: + raise LibError("Unable to build shellphish-qemu-linux") + + shutil.copyfile(os.path.join(QEMU_REPO_PATH_LINUX, "i386-linux-user", "qemu-i386"), QEMU_PATH_LINUX_I386) + shutil.copyfile(os.path.join(QEMU_REPO_PATH_LINUX, "x86_64-linux-user", "qemu-x86_64"), QEMU_PATH_LINUX_X86_64) + + shutil.copyfile(os.path.join(QEMU_REPO_PATH_LINUX, "mipsel-linux-user", "qemu-mipsel"), QEMU_PATH_LINUX_MIPSEL) + shutil.copyfile(os.path.join(QEMU_REPO_PATH_LINUX, "mips-linux-user", "qemu-mips"), QEMU_PATH_LINUX_MIPS) + shutil.copyfile(os.path.join(QEMU_REPO_PATH_LINUX, "mips64-linux-user", "qemu-mips64"), QEMU_PATH_LINUX_MIPS64) + + shutil.copyfile(os.path.join(QEMU_REPO_PATH_LINUX, "ppc-linux-user", "qemu-ppc"), QEMU_PATH_LINUX_PPC) + shutil.copyfile(os.path.join(QEMU_REPO_PATH_LINUX, "ppc64-linux-user", "qemu-ppc64"), QEMU_PATH_LINUX_PPC64) + + shutil.copyfile(os.path.join(QEMU_REPO_PATH_LINUX, "arm-linux-user", "qemu-arm"), QEMU_PATH_LINUX_ARM) + shutil.copyfile(os.path.join(QEMU_REPO_PATH_LINUX, "aarch64-linux-user", "qemu-aarch64"), QEMU_PATH_LINUX_AARCH64) + + os.chmod(QEMU_PATH_LINUX_I386, 0o755) + os.chmod(QEMU_PATH_LINUX_X86_64, 0o755) + os.chmod(QEMU_PATH_LINUX_MIPSEL, 0o755) + os.chmod(QEMU_PATH_LINUX_MIPS, 0o755) + os.chmod(QEMU_PATH_LINUX_MIPS64, 0o755) + os.chmod(QEMU_PATH_LINUX_PPC, 0o755) + os.chmod(QEMU_PATH_LINUX_PPC64, 0o755) + os.chmod(QEMU_PATH_LINUX_ARM, 0o755) + os.chmod(QEMU_PATH_LINUX_AARCH64, 0o755) + + + +def _build_qemus(): + if subprocess.call(['rm','-rf', QEMU_REPO_PATH_LINUX]) != 0: + raise LibError("Something wrong while deleting folder!") + + if subprocess.call(['git', 'clone', '--branch', 'v2.3.0', '--depth=1', TRACER_QEMU_REPO_LINUX, QEMU_REPO_PATH_LINUX]) != 0: + raise LibError("Something went wrong!!") + + print("Patching Qemu to deal with CGC") + if subprocess.call(['git', '-C', QEMU_REPO_PATH_LINUX, 'apply', '--whitespace=warn', '--reject', QEMU_LINUX_CGC_PATCH, '-p6']) != 0: + pass + print("Configuring CGC tracer qemu...") - if subprocess.call(['make', 'clean'], cwd=QEMU_REPO_PATH_CGC_BASE) != 0: + if subprocess.call(['make', 'clean'], cwd=QEMU_REPO_PATH_LINUX) != 0: raise LibError("Unable to clean shellphish-qemu-cgc-tracer") - if subprocess.call(['./cgc_configure_tracer_opt'], cwd=QEMU_REPO_PATH_CGC_BASE) != 0: + if subprocess.call(['./cgc_configure_tracer_opt'], cwd=QEMU_REPO_PATH_LINUX) != 0: raise LibError("Unable to configure shellphish-qemu-cgc-tracer") print("Building CGC tracer qemu...") - if subprocess.call(['make', '-j4'], cwd=QEMU_REPO_PATH_CGC_BASE) != 0: + if subprocess.call(['make', '-j4'], cwd=QEMU_REPO_PATH_LINUX) != 0: raise LibError("Unable to build shellphish-qemu-cgc") - shutil.copyfile(os.path.join(QEMU_REPO_PATH_CGC_BASE, "i386-linux-user", "qemu-i386"), QEMU_PATH_CGC_TRACER) + shutil.copyfile(os.path.join(QEMU_REPO_PATH_LINUX, "i386-linux-user", "qemu-i386"), QEMU_PATH_CGC_TRACER) - if subprocess.call(['make', 'clean'], cwd=QEMU_REPO_PATH_CGC_BASE) != 0: + if subprocess.call(['make', 'clean'], cwd=QEMU_REPO_PATH_LINUX) != 0: raise LibError("Unable to clean shellphish-qemu-cgc") print("Configuring CGC nxtracer qemu...") - if subprocess.call(['./cgc_configure_nxtracer_opt'], cwd=QEMU_REPO_PATH_CGC_BASE) != 0: + if subprocess.call(['./cgc_configure_nxtracer_opt'], cwd=QEMU_REPO_PATH_LINUX) != 0: raise LibError("Unable to configure shellphish-qemu-cgc-nxtracer") print("Building CGC nxtracer qemu...") - if subprocess.call(['make', '-j4'], cwd=QEMU_REPO_PATH_CGC_BASE) != 0: + if subprocess.call(['make', '-j4'], cwd=QEMU_REPO_PATH_LINUX) != 0: raise LibError("Unable to build shellphish-qemu-cgc-nxtracer") - shutil.copyfile(os.path.join(QEMU_REPO_PATH_CGC_BASE, "i386-linux-user", "qemu-i386"), QEMU_PATH_CGC_NXTRACER) + shutil.copyfile(os.path.join(QEMU_REPO_PATH_LINUX, "i386-linux-user", "qemu-i386"), QEMU_PATH_CGC_NXTRACER) - if subprocess.call(['make', 'clean'], cwd=QEMU_REPO_PATH_CGC_BASE) != 0: + if subprocess.call(['make', 'clean'], cwd=QEMU_REPO_PATH_LINUX) != 0: raise LibError("Unable to clean shellphish-qemu-cgc") print("Configuring CGC base qemu...") - if subprocess.call(['./cgc_configure_opt'], cwd=QEMU_REPO_PATH_CGC_BASE) != 0: + if subprocess.call(['./cgc_configure_opt'], cwd=QEMU_REPO_PATH_LINUX) != 0: raise LibError("Unable to configure shellphish-qemu-cgc-base") print("Building CGC base qemu...") - if subprocess.call(['make', '-j4'], cwd=QEMU_REPO_PATH_CGC_BASE) != 0: - raise LibError("Unable to build shellphish-qemu-cgc") - - shutil.copyfile(os.path.join(QEMU_REPO_PATH_CGC_BASE, "i386-linux-user", "qemu-i386"), QEMU_PATH_CGC_BASE) - - print("Configuring Linux qemu...") - if subprocess.call(['./tracer-config'], cwd=QEMU_REPO_PATH_LINUX) != 0: - raise LibError("Unable to configure shellphish-qemu-linux") - print("Building Linux qemu...") if subprocess.call(['make', '-j4'], cwd=QEMU_REPO_PATH_LINUX) != 0: - raise LibError("Unable to build shellphish-qemu-linux") - - - shutil.copyfile(os.path.join(QEMU_REPO_PATH_LINUX, "i386-linux-user", "qemu-i386"), QEMU_PATH_LINUX_I386) - shutil.copyfile(os.path.join(QEMU_REPO_PATH_LINUX, "x86_64-linux-user", "qemu-x86_64"), QEMU_PATH_LINUX_X86_64) - - shutil.copyfile(os.path.join(QEMU_REPO_PATH_LINUX, "mipsel-linux-user", "qemu-mipsel"), QEMU_PATH_LINUX_MIPSEL) - shutil.copyfile(os.path.join(QEMU_REPO_PATH_LINUX, "mips-linux-user", "qemu-mips"), QEMU_PATH_LINUX_MIPS) - shutil.copyfile(os.path.join(QEMU_REPO_PATH_LINUX, "mips64-linux-user", "qemu-mips64"), QEMU_PATH_LINUX_MIPS64) - - shutil.copyfile(os.path.join(QEMU_REPO_PATH_LINUX, "ppc-linux-user", "qemu-ppc"), QEMU_PATH_LINUX_PPC) - shutil.copyfile(os.path.join(QEMU_REPO_PATH_LINUX, "ppc64-linux-user", "qemu-ppc64"), QEMU_PATH_LINUX_PPC64) + raise LibError("Unable to build shellphish-qemu-cgc") - shutil.copyfile(os.path.join(QEMU_REPO_PATH_LINUX, "arm-linux-user", "qemu-arm"), QEMU_PATH_LINUX_ARM) - shutil.copyfile(os.path.join(QEMU_REPO_PATH_LINUX, "aarch64-linux-user", "qemu-aarch64"), QEMU_PATH_LINUX_AARCH64) + shutil.copyfile(os.path.join(QEMU_REPO_PATH_LINUX, "i386-linux-user", "qemu-i386"), QEMU_PATH_CGC_BASE) os.chmod(QEMU_PATH_CGC_BASE, 0o755) os.chmod(QEMU_PATH_CGC_TRACER, 0o755) os.chmod(QEMU_PATH_CGC_NXTRACER, 0o755) - os.chmod(QEMU_PATH_LINUX_I386, 0o755) - os.chmod(QEMU_PATH_LINUX_X86_64, 0o755) - os.chmod(QEMU_PATH_LINUX_MIPSEL, 0o755) - os.chmod(QEMU_PATH_LINUX_MIPS, 0o755) - os.chmod(QEMU_PATH_LINUX_MIPS64, 0o755) - os.chmod(QEMU_PATH_LINUX_PPC, 0o755) - os.chmod(QEMU_PATH_LINUX_PPC64, 0o755) - os.chmod(QEMU_PATH_LINUX_ARM, 0o755) - os.chmod(QEMU_PATH_LINUX_AARCH64, 0o755) try: - cgc_base_ver = subprocess.check_output([QEMU_PATH_CGC_BASE, '-version']) cgc_tracer_ver = subprocess.check_output([QEMU_PATH_CGC_TRACER, '-version']) cgc_nxtracer_ver = subprocess.check_output([QEMU_PATH_CGC_NXTRACER, '-version']) - assert b'AFL' not in cgc_base_ver assert b'AFL' not in cgc_tracer_ver assert b'AFL' not in cgc_nxtracer_ver - assert b'TRACER' not in cgc_base_ver assert b'TRACER' in cgc_tracer_ver assert b'TRACER' in cgc_nxtracer_ver - assert b'enforce NX' not in cgc_base_ver # Playing it safe assert b'enforce NX' not in cgc_tracer_ver # Playing it safe assert b'enforce NX' in cgc_nxtracer_ver # Mainly used by Antonio for CI tests except subprocess.CalledProcessError as e: @@ -189,14 +178,12 @@ def _build_qemus(): class build(_build): def run(self): - self.execute(_clone_cgc_qemu, (), msg="Cloning CGC QEMU") self.execute(_clone_linux_qemu, (), msg="Cloning Linux QEMU") self.execute(_build_qemus, (), msg="Building Tracer QEMU") _build.run(self) class develop(_develop): def run(self): - self.execute(_clone_cgc_qemu, (), msg="Cloning CGC QEMU") self.execute(_clone_linux_qemu, (), msg="Cloning Linux QEMU") self.execute(_build_qemus, (), msg="Building Tracer QEMU") _develop.run(self)