qemu/darwin-user/syscall.c
<<
>>
Prefs
   1/*
   2 *  Darwin syscalls
   3 *
   4 *  Copyright (c) 2003 Fabrice Bellard
   5 *  Copyright (c) 2006 Pierre d'Herbemont
   6 *
   7 *  This program is free software; you can redistribute it and/or modify
   8 *  it under the terms of the GNU General Public License as published by
   9 *  the Free Software Foundation; either version 2 of the License, or
  10 *  (at your option) any later version.
  11 *
  12 *  This program is distributed in the hope that it will be useful,
  13 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 *  GNU General Public License for more details.
  16 *
  17 *  You should have received a copy of the GNU General Public License
  18 *  along with this program; if not, write to the Free Software
  19 *  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
  20 *  MA 02110-1301, USA.
  21 */
  22#include <fcntl.h>
  23#include <stdio.h>
  24#include <stdlib.h>
  25#include <errno.h>
  26
  27#include <mach/host_info.h>
  28#include <mach/mach.h>
  29#include <mach/mach_time.h>
  30#include <mach/message.h>
  31
  32#include <pthread.h>
  33#include <dirent.h>
  34
  35#include <sys/stat.h>
  36#include <sys/syscall.h>
  37#include <sys/sysctl.h>
  38#include <sys/types.h>
  39#include <unistd.h>
  40#include <sys/ioctl.h>
  41#include <sys/mman.h>
  42#include <sys/types.h>
  43#include <sys/dirent.h>
  44#include <sys/uio.h>
  45#include <sys/termios.h>
  46#include <sys/ptrace.h>
  47#include <net/if.h>
  48
  49#include <sys/param.h>
  50#include <sys/mount.h>
  51
  52#include <sys/attr.h>
  53
  54#include <mach/ndr.h>
  55#include <mach/mig_errors.h>
  56
  57#include <sys/xattr.h>
  58
  59#include "qemu.h"
  60
  61//#define DEBUG_SYSCALL
  62
  63#ifdef DEBUG_SYSCALL
  64# define DEBUG_FORCE_ENABLE_LOCAL() int __DEBUG_qemu_user_force_enable = 1
  65# define DEBUG_BEGIN_ENABLE  __DEBUG_qemu_user_force_enable = 1;
  66# define DEBUG_END_ENABLE  __DEBUG_qemu_user_force_enable = 0;
  67
  68# define DEBUG_DISABLE_ALL() static int __DEBUG_qemu_user_force_enable = 0
  69# define DEBUG_ENABLE_ALL()  static int __DEBUG_qemu_user_force_enable = 1
  70    DEBUG_ENABLE_ALL();
  71
  72# define DPRINTF(...) do { qemu_log(__VA_ARGS__); \
  73                           if(__DEBUG_qemu_user_force_enable) fprintf(stderr, __VA_ARGS__); \
  74                         } while(0)
  75#else
  76# define DEBUG_FORCE_ENABLE_LOCAL()
  77# define DEBUG_BEGIN_ENABLE
  78# define DEBUG_END_ENABLE
  79
  80# define DPRINTF(...) do { qemu_log(__VA_ARGS__); } while(0)
  81#endif
  82
  83enum {
  84    bswap_out = 0,
  85    bswap_in = 1
  86};
  87
  88extern const char *interp_prefix;
  89
  90static inline long get_errno(long ret)
  91{
  92    if (ret == -1)
  93        return -errno;
  94    else
  95        return ret;
  96}
  97
  98static inline int is_error(long ret)
  99{
 100    return (unsigned long)ret >= (unsigned long)(-4096);
 101}
 102
 103/* ------------------------------------------------------------
 104   Mach syscall handling
 105*/
 106
 107void static inline print_description_msg_header(mach_msg_header_t *hdr)
 108{
 109    char *name = NULL;
 110    int i;
 111    struct { int number; char *name; } msg_name[] =
 112    {
 113        /* see http://fxr.watson.org/fxr/source/compat/mach/mach_namemap.c?v=NETBSD */
 114        { 200,      "host_info" },
 115        { 202,      "host_page_size" },
 116        { 206,      "host_get_clock_service" },
 117        { 206,      "host_get_clock_service" },
 118        { 206,      "host_get_clock_service" },
 119        { 306,      "host_get_clock_service" },
 120        { 3204,     "mach_port_allocate" },
 121        { 3206,     "mach_port_deallocate" },
 122        { 3404,     "mach_ports_lookup" },
 123        { 3409,     "mach_task_get_special_port" },
 124        { 3414,     "mach_task_get_exception_ports" },
 125        { 3418,     "mach_semaphore_create" },
 126        { 3504,     "mach_semaphore_create" },
 127        { 3509,     "mach_semaphore_create" },
 128        { 3518,     "semaphore_create" },
 129        { 3616,     "thread_policy" },
 130        { 3801,     "vm_allocate" },
 131        { 3802,     "vm_deallocate" },
 132        { 3802,     "vm_deallocate" },
 133        { 3803,     "vm_protect" },
 134        { 3812,     "vm_map" },
 135        { 4241776,  "lu_message_send_id" },  /* lookupd */
 136        { 4241876,  "lu_message_reply_id" }, /* lookupd */
 137    };
 138
 139    for(i = 0; i < ARRAY_SIZE(msg_name); i++) {
 140        if(msg_name[i].number == hdr->msgh_id)
 141        {
 142            name = msg_name[i].name;
 143            break;
 144        }
 145    }
 146    if(!name)
 147        DPRINTF("unknown mach msg %d 0x%x\n", hdr->msgh_id, hdr->msgh_id);
 148    else
 149        DPRINTF("%s\n", name);
 150#if 0
 151    DPRINTF("Bits: %8x\n", hdr->msgh_bits);
 152    DPRINTF("Size: %8x\n", hdr->msgh_size);
 153    DPRINTF("Rmte: %8x\n", hdr->msgh_remote_port);
 154    DPRINTF("Locl: %8x\n", hdr->msgh_local_port);
 155    DPRINTF("Rsrv: %8x\n", hdr->msgh_reserved);
 156
 157    DPRINTF("Id  : %8x\n", hdr->msgh_id);
 158
 159    NDR_record_t *ndr = (NDR_record_t *)(hdr + 1);
 160    DPRINTF("hdr = %p, sizeof(hdr) = %x, NDR = %p\n", hdr, (unsigned int)sizeof(mach_msg_header_t), ndr);
 161    DPRINTF("%d %d %d %d %d %d %d %d\n",
 162           ndr->mig_vers, ndr->if_vers, ndr->reserved1, ndr->mig_encoding,
 163           ndr->int_rep, ndr->char_rep, ndr->float_rep, ndr->reserved2);
 164#endif
 165}
 166
 167static inline void print_mach_msg_return(mach_msg_return_t ret)
 168{
 169    int i, found = 0;
 170#define MACH_MSG_RET(msg) { msg, #msg }
 171    struct { int code; char *name; } msg_name[] =
 172    {
 173        /* ref: http://darwinsource.opendarwin.org/10.4.2/xnu-792.2.4/osfmk/man/mach_msg.html */
 174        /* send message */
 175        MACH_MSG_RET(MACH_SEND_MSG_TOO_SMALL),
 176        MACH_MSG_RET(MACH_SEND_NO_BUFFER),
 177        MACH_MSG_RET(MACH_SEND_INVALID_DATA),
 178        MACH_MSG_RET(MACH_SEND_INVALID_HEADER),
 179        MACH_MSG_RET(MACH_SEND_INVALID_DEST),
 180        MACH_MSG_RET(MACH_SEND_INVALID_NOTIFY),
 181        MACH_MSG_RET(MACH_SEND_INVALID_REPLY),
 182        MACH_MSG_RET(MACH_SEND_INVALID_TRAILER),
 183        MACH_MSG_RET(MACH_SEND_INVALID_MEMORY),
 184        MACH_MSG_RET(MACH_SEND_INVALID_RIGHT),
 185        MACH_MSG_RET(MACH_SEND_INVALID_TYPE),
 186        MACH_MSG_RET(MACH_SEND_INTERRUPTED),
 187        MACH_MSG_RET(MACH_SEND_TIMED_OUT),
 188
 189        MACH_MSG_RET(MACH_RCV_BODY_ERROR),
 190        MACH_MSG_RET(MACH_RCV_HEADER_ERROR),
 191
 192        MACH_MSG_RET(MACH_RCV_IN_SET),
 193        MACH_MSG_RET(MACH_RCV_INTERRUPTED),
 194
 195        MACH_MSG_RET(MACH_RCV_INVALID_DATA),
 196        MACH_MSG_RET(MACH_RCV_INVALID_NAME),
 197        MACH_MSG_RET(MACH_RCV_INVALID_NOTIFY),
 198        MACH_MSG_RET(MACH_RCV_INVALID_TRAILER),
 199        MACH_MSG_RET(MACH_RCV_INVALID_TYPE),
 200
 201        MACH_MSG_RET(MACH_RCV_PORT_CHANGED),
 202        MACH_MSG_RET(MACH_RCV_PORT_DIED),
 203
 204        MACH_MSG_RET(MACH_RCV_SCATTER_SMALL),
 205        MACH_MSG_RET(MACH_RCV_TIMED_OUT),
 206        MACH_MSG_RET(MACH_RCV_TOO_LARGE)
 207    };
 208#undef MACH_MSG_RET
 209
 210    if( ret == MACH_MSG_SUCCESS)
 211        DPRINTF("MACH_MSG_SUCCESS\n");
 212    else
 213    {
 214        for( i = 0; i < ARRAY_SIZE(msg_name); i++) {
 215            if(msg_name[i].code == ret) {
 216                DPRINTF("%s\n", msg_name[i].name);
 217                found = 1;
 218                break;
 219            }
 220        }
 221        if(!found)
 222            qerror("unknow mach message ret code %d\n", ret);
 223    }
 224}
 225
 226static inline void swap_mach_msg_header(mach_msg_header_t *hdr)
 227{
 228    hdr->msgh_bits = tswap32(hdr->msgh_bits);
 229    hdr->msgh_size = tswap32(hdr->msgh_size);
 230    hdr->msgh_remote_port = tswap32(hdr->msgh_remote_port);
 231    hdr->msgh_local_port = tswap32(hdr->msgh_local_port);
 232    hdr->msgh_reserved = tswap32(hdr->msgh_reserved);
 233    hdr->msgh_id = tswap32(hdr->msgh_id);
 234}
 235
 236struct complex_msg {
 237            mach_msg_header_t hdr;
 238            mach_msg_body_t body;
 239};
 240
 241static inline void swap_mach_msg_body(struct complex_msg *complex_msg, int bswap)
 242{
 243    mach_msg_port_descriptor_t *descr = (mach_msg_port_descriptor_t *)(complex_msg+1);
 244    int i,j;
 245
 246    if(bswap == bswap_in)
 247        tswap32s(&complex_msg->body.msgh_descriptor_count);
 248
 249    DPRINTF("body.msgh_descriptor_count %d\n", complex_msg->body.msgh_descriptor_count);
 250
 251    for(i = 0; i < complex_msg->body.msgh_descriptor_count; i++) {
 252        switch(descr->type)
 253        {
 254            case MACH_MSG_PORT_DESCRIPTOR:
 255                tswap32s(&descr->name);
 256                descr++;
 257                break;
 258            case MACH_MSG_OOL_DESCRIPTOR:
 259            {
 260                mach_msg_ool_descriptor_t *ool = (void *)descr;
 261                tswap32s((uint32_t *)&ool->address);
 262                tswap32s(&ool->size);
 263
 264                descr = (mach_msg_port_descriptor_t *)(ool+1);
 265                break;
 266            }
 267            case MACH_MSG_OOL_PORTS_DESCRIPTOR:
 268            {
 269                mach_msg_ool_ports_descriptor_t *ool_ports = (void *)descr;
 270                mach_port_name_t * port_names;
 271
 272                if(bswap == bswap_in)
 273                {
 274                    tswap32s((uint32_t *)&ool_ports->address);
 275                    tswap32s(&ool_ports->count);
 276                }
 277
 278                port_names = ool_ports->address;
 279
 280                for(j = 0; j < ool_ports->count; j++)
 281                    tswap32s(&port_names[j]);
 282
 283                if(bswap == bswap_out)
 284                {
 285                    tswap32s((uint32_t *)&ool_ports->address);
 286                    tswap32s(&ool_ports->count);
 287                }
 288
 289                descr = (mach_msg_port_descriptor_t *)(ool_ports+1);
 290                break;
 291            }
 292            default: qerror("unknow mach msg descriptor type %x\n", descr->type);
 293        }
 294    }
 295    if(bswap == bswap_out)
 296        tswap32s(&complex_msg->body.msgh_descriptor_count);
 297}
 298
 299static inline void swap_mach_msg(mach_msg_header_t *hdr, int bswap)
 300{
 301    if (bswap == bswap_out && hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX)
 302        swap_mach_msg_body((struct complex_msg *)hdr, bswap);
 303
 304    swap_mach_msg_header(hdr);
 305
 306    if (bswap == bswap_in && hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX)
 307        swap_mach_msg_body((struct complex_msg *)hdr, bswap);
 308}
 309
 310static inline uint32_t target_mach_msg_trap(
 311        mach_msg_header_t *hdr, uint32_t options, uint32_t send_size,
 312        uint32_t rcv_size, uint32_t rcv_name, uint32_t time_out, uint32_t notify)
 313{
 314    extern int mach_msg_trap(mach_msg_header_t *, mach_msg_option_t,
 315          mach_msg_size_t, mach_msg_size_t, mach_port_t,
 316          mach_msg_timeout_t, mach_port_t);
 317    mach_msg_audit_trailer_t *trailer;
 318    mach_msg_id_t msg_id;
 319    uint32_t ret = 0;
 320    int i;
 321
 322    swap_mach_msg(hdr, bswap_in);
 323
 324    msg_id = hdr->msgh_id;
 325
 326    print_description_msg_header(hdr);
 327
 328    ret = mach_msg_trap(hdr, options, send_size, rcv_size, rcv_name, time_out, notify);
 329
 330    print_mach_msg_return(ret);
 331
 332    if( (options & MACH_RCV_MSG) && (REQUESTED_TRAILER_SIZE(options) > 0) )
 333    {
 334        /* XXX: the kernel always return the full trailer with MACH_SEND_MSG, so we should
 335                probably always bswap it  */
 336        /* warning: according to Mac OS X Internals (the book) msg_size might be expressed in
 337                    natural_t units but according to xnu/osfmk/mach/message.h: "The size of
 338                    the message must be specified in bytes" */
 339        trailer = (mach_msg_audit_trailer_t *)((uint8_t *)hdr + hdr->msgh_size);
 340        /* XXX: Should probably do that based on the option asked by the sender, but dealing
 341        with kernel answer seems more sound */
 342        switch(trailer->msgh_trailer_size)
 343        {
 344            case sizeof(mach_msg_audit_trailer_t):
 345                for(i = 0; i < 8; i++)
 346                    tswap32s(&trailer->msgh_audit.val[i]);
 347                /* Fall in mach_msg_security_trailer_t case */
 348            case sizeof(mach_msg_security_trailer_t):
 349                tswap32s(&trailer->msgh_sender.val[0]);
 350                tswap32s(&trailer->msgh_sender.val[1]);
 351                /* Fall in mach_msg_seqno_trailer_t case */
 352            case sizeof(mach_msg_seqno_trailer_t):
 353                tswap32s(&trailer->msgh_seqno);
 354                /* Fall in mach_msg_trailer_t case */
 355            case sizeof(mach_msg_trailer_t):
 356                tswap32s(&trailer->msgh_trailer_type);
 357                tswap32s(&trailer->msgh_trailer_size);
 358                break;
 359            case 0:
 360                /* Safer not to byteswap, but probably wrong */
 361                break;
 362            default:
 363                qerror("unknow trailer type given its size %d\n", trailer->msgh_trailer_size);
 364                break;
 365        }
 366    }
 367
 368    /* Special message handling */
 369    switch (msg_id) {
 370        case 200: /* host_info */
 371        {
 372            mig_reply_error_t *err = (mig_reply_error_t *)hdr;
 373            struct {
 374                uint32_t unknow1;
 375                uint32_t max_cpus;
 376                uint32_t avail_cpus;
 377                uint32_t memory_size;
 378                uint32_t cpu_type;
 379                uint32_t cpu_subtype;
 380            } *data = (void *)(err+1);
 381
 382            DPRINTF("maxcpu = 0x%x\n",   data->max_cpus);
 383            DPRINTF("numcpu = 0x%x\n",   data->avail_cpus);
 384            DPRINTF("memsize = 0x%x\n",  data->memory_size);
 385
 386#if defined(TARGET_I386)
 387            data->cpu_type = CPU_TYPE_I386;
 388            DPRINTF("cpu_type changed to 0x%x(i386)\n", data->cpu_type);
 389            data->cpu_subtype = CPU_SUBTYPE_PENT;
 390            DPRINTF("cpu_subtype changed to 0x%x(i386_pent)\n", data->cpu_subtype);
 391#elif defined(TARGET_PPC)
 392            data->cpu_type = CPU_TYPE_POWERPC;
 393            DPRINTF("cpu_type changed to 0x%x(ppc)\n", data->cpu_type);
 394            data->cpu_subtype = CPU_SUBTYPE_POWERPC_750;
 395            DPRINTF("cpu_subtype changed to 0x%x(ppc_all)\n", data->cpu_subtype);
 396#else
 397# error target not supported
 398#endif
 399            break;
 400        }
 401        case 202: /* host_page_size */
 402        {
 403            mig_reply_error_t *err = (mig_reply_error_t *)hdr;
 404            uint32_t *pagesize = (uint32_t *)(err+1);
 405
 406            DPRINTF("pagesize = %d\n", *pagesize);
 407            break;
 408        }
 409        default: break;
 410    }
 411
 412    swap_mach_msg(hdr, bswap_out);
 413
 414    return ret;
 415}
 416
 417long do_mach_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
 418                uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
 419                uint32_t arg8)
 420{
 421    extern uint32_t mach_reply_port(void);
 422
 423    long ret = 0;
 424
 425    arg1 = tswap32(arg1);
 426    arg2 = tswap32(arg2);
 427    arg3 = tswap32(arg3);
 428    arg4 = tswap32(arg4);
 429    arg5 = tswap32(arg5);
 430    arg6 = tswap32(arg6);
 431    arg7 = tswap32(arg7);
 432    arg8 = tswap32(arg8);
 433
 434    DPRINTF("mach syscall %d : " , num);
 435
 436    switch(num) {
 437    /* see xnu/osfmk/mach/syscall_sw.h */
 438    case -26:
 439        DPRINTF("mach_reply_port()\n");
 440        ret = mach_reply_port();
 441        break;
 442    case -27:
 443        DPRINTF("mach_thread_self()\n");
 444        ret = mach_thread_self();
 445        break;
 446    case -28:
 447        DPRINTF("mach_task_self()\n");
 448        ret = mach_task_self();
 449        break;
 450    case -29:
 451        DPRINTF("mach_host_self()\n");
 452        ret = mach_host_self();
 453        break;
 454    case -31:
 455        DPRINTF("mach_msg_trap(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
 456                arg1, arg2, arg3, arg4, arg5, arg6, arg7);
 457        ret = target_mach_msg_trap((mach_msg_header_t *)arg1, arg2, arg3, arg4, arg5, arg6, arg7);
 458        break;
 459/* may need more translation if target arch is different from host */
 460#if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__))
 461    case -33:
 462        DPRINTF("semaphore_signal_trap(0x%x)\n", arg1);
 463        ret = semaphore_signal_trap(arg1);
 464        break;
 465    case -34:
 466        DPRINTF("semaphore_signal_all_trap(0x%x)\n", arg1);
 467        ret = semaphore_signal_all_trap(arg1);
 468        break;
 469    case -35:
 470        DPRINTF("semaphore_signal_thread_trap(0x%x)\n", arg1, arg2);
 471        ret = semaphore_signal_thread_trap(arg1,arg2);
 472        break;
 473#endif
 474    case -36:
 475        DPRINTF("semaphore_wait_trap(0x%x)\n", arg1);
 476        extern int semaphore_wait_trap(int); // XXX: is there any header for that?
 477        ret = semaphore_wait_trap(arg1);
 478        break;
 479/* may need more translation if target arch is different from host */
 480#if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__))
 481    case -37:
 482        DPRINTF("semaphore_wait_signal_trap(0x%x, 0x%x)\n", arg1, arg2);
 483        ret = semaphore_wait_signal_trap(arg1,arg2);
 484        break;
 485#endif
 486    case -43:
 487        DPRINTF("map_fd(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
 488                arg1, arg2, arg3, arg4, arg5);
 489        ret = map_fd(arg1, arg2, (void*)arg3, arg4, arg5);
 490        tswap32s((uint32_t*)arg3);
 491        break;
 492/* may need more translation if target arch is different from host */
 493#if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__))
 494    case -61:
 495        DPRINTF("syscall_thread_switch(0x%x, 0x%x, 0x%x)\n",
 496                arg1, arg2, arg3);
 497        ret = syscall_thread_switch(arg1, arg2, arg3);  // just a hint to the scheduler; can drop?
 498        break;
 499#endif
 500    case -89:
 501        DPRINTF("mach_timebase_info(0x%x)\n", arg1);
 502        struct mach_timebase_info info;
 503        ret = mach_timebase_info(&info);
 504        if(!is_error(ret))
 505        {
 506            struct mach_timebase_info *outInfo = (void*)arg1;
 507            outInfo->numer = tswap32(info.numer);
 508            outInfo->denom = tswap32(info.denom);
 509        }
 510        break;
 511    case -90:
 512        DPRINTF("mach_wait_until()\n");
 513        extern int mach_wait_until(uint64_t); // XXX: is there any header for that?
 514        ret = mach_wait_until(((uint64_t)arg2<<32) | (uint64_t)arg1);
 515        break;
 516    case -91:
 517        DPRINTF("mk_timer_create()\n");
 518        extern int mk_timer_create(); // XXX: is there any header for that?
 519        ret = mk_timer_create();
 520        break;
 521    case -92:
 522        DPRINTF("mk_timer_destroy()\n");
 523        extern int mk_timer_destroy(int); // XXX: is there any header for that?
 524        ret = mk_timer_destroy(arg1);
 525        break;
 526    case -93:
 527        DPRINTF("mk_timer_create()\n");
 528        extern int mk_timer_arm(int, uint64_t); // XXX: is there any header for that?
 529        ret = mk_timer_arm(arg1, ((uint64_t)arg3<<32) | (uint64_t)arg2);
 530        break;
 531    case -94:
 532        DPRINTF("mk_timer_cancel()\n");
 533        extern int mk_timer_cancel(int, uint64_t *); // XXX: is there any header for that?
 534        ret = mk_timer_cancel(arg1, (uint64_t *)arg2);
 535        if((!is_error(ret)) && arg2)
 536            tswap64s((uint64_t *)arg2);
 537        break;
 538    default:
 539        gemu_log("qemu: Unsupported mach syscall: %d(0x%x)\n", num, num);
 540        gdb_handlesig (cpu_env, SIGTRAP);
 541        exit(0);
 542        break;
 543    }
 544    return ret;
 545}
 546
 547/* ------------------------------------------------------------
 548   thread type syscall handling
 549*/
 550long do_thread_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
 551                uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
 552                uint32_t arg8)
 553{
 554    extern uint32_t cthread_set_self(uint32_t);
 555    extern uint32_t processor_facilities_used(void);
 556    long ret = 0;
 557
 558    arg1 = tswap32(arg1);
 559    arg2 = tswap32(arg2);
 560    arg3 = tswap32(arg3);
 561    arg4 = tswap32(arg4);
 562    arg5 = tswap32(arg5);
 563    arg6 = tswap32(arg6);
 564    arg7 = tswap32(arg7);
 565    arg8 = tswap32(arg8);
 566
 567    DPRINTF("thread syscall %d : " , num);
 568
 569    switch(num) {
 570#ifdef TARGET_I386
 571    case 0x3:
 572#endif
 573    case 0x7FF1: /* cthread_set_self */
 574        DPRINTF("cthread_set_self(0x%x)\n", (unsigned int)arg1);
 575        ret = cthread_set_self(arg1);
 576#ifdef TARGET_I386
 577        /* we need to update the LDT with the address of the thread */
 578        write_dt((void *)(((CPUX86State *) cpu_env)->ldt.base + (4 * sizeof(uint64_t))), arg1, 1,
 579                 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
 580                 (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
 581        /* New i386 convention, %gs should be set to our this LDT entry */
 582        cpu_x86_load_seg(cpu_env, R_GS, 0x27);
 583        /* Old i386 convention, the kernel returns the selector for the cthread (pre-10.4.8?)*/
 584        ret = 0x27;
 585#endif
 586        break;
 587    case 0x7FF2: /* Called the super-fast pthread_self handler by the apple guys */
 588        DPRINTF("pthread_self()\n");
 589        ret = (uint32_t)pthread_self();
 590        break;
 591    case 0x7FF3:
 592        DPRINTF("processor_facilities_used()\n");
 593#ifdef __i386__
 594        qerror("processor_facilities_used: not implemented!\n");
 595#else
 596        ret = (uint32_t)processor_facilities_used();
 597#endif
 598        break;
 599    default:
 600        gemu_log("qemu: Unsupported thread syscall: %d(0x%x)\n", num, num);
 601        gdb_handlesig (cpu_env, SIGTRAP);
 602        exit(0);
 603        break;
 604    }
 605    return ret;
 606}
 607
 608/* ------------------------------------------------------------
 609   ioctl handling
 610*/
 611static inline void byteswap_termios(struct termios *t)
 612{
 613    tswap32s((uint32_t*)&t->c_iflag);
 614    tswap32s((uint32_t*)&t->c_oflag);
 615    tswap32s((uint32_t*)&t->c_cflag);
 616    tswap32s((uint32_t*)&t->c_lflag);
 617    /* 20 (char) bytes then */
 618    tswap32s((uint32_t*)&t->c_ispeed);
 619    tswap32s((uint32_t*)&t->c_ospeed);
 620}
 621
 622static inline void byteswap_winsize(struct winsize *w)
 623{
 624    tswap16s(&w->ws_row);
 625    tswap16s(&w->ws_col);
 626    tswap16s(&w->ws_xpixel);
 627    tswap16s(&w->ws_ypixel);
 628}
 629
 630#define STRUCT(name, list...) STRUCT_ ## name,
 631#define STRUCT_SPECIAL(name) STRUCT_ ## name,
 632enum {
 633#include "ioctls_types.h"
 634};
 635#undef STRUCT
 636#undef STRUCT_SPECIAL
 637
 638#define STRUCT(name, list...) const argtype struct_ ## name ## _def[] = { list, TYPE_NULL };
 639#define STRUCT_SPECIAL(name)
 640#include "ioctls_types.h"
 641#undef STRUCT
 642#undef STRUCT_SPECIAL
 643
 644typedef struct IOCTLEntry {
 645    unsigned int target_cmd;
 646    unsigned int host_cmd;
 647    const char *name;
 648    int access;
 649    const argtype arg_type[5];
 650} IOCTLEntry;
 651
 652#define IOC_R 0x0001
 653#define IOC_W 0x0002
 654#define IOC_RW (IOC_R | IOC_W)
 655
 656#define MAX_STRUCT_SIZE 4096
 657
 658static IOCTLEntry ioctl_entries[] = {
 659#define IOCTL(cmd, access, types...) \
 660    { cmd, cmd, #cmd, access, { types } },
 661#include "ioctls.h"
 662    { 0, 0, },
 663};
 664
 665/* ??? Implement proper locking for ioctls.  */
 666static long do_ioctl(long fd, long cmd, long arg)
 667{
 668    const IOCTLEntry *ie;
 669    const argtype *arg_type;
 670    int ret;
 671    uint8_t buf_temp[MAX_STRUCT_SIZE];
 672    int target_size;
 673    void *argptr;
 674
 675    ie = ioctl_entries;
 676    for(;;) {
 677        if (ie->target_cmd == 0) {
 678            gemu_log("Unsupported ioctl: cmd=0x%04lx\n", cmd);
 679            return -ENOSYS;
 680        }
 681        if (ie->target_cmd == cmd)
 682            break;
 683        ie++;
 684    }
 685    arg_type = ie->arg_type;
 686#if defined(DEBUG)
 687    gemu_log("ioctl: cmd=0x%04lx (%s)\n", cmd, ie->name);
 688#endif
 689    switch(arg_type[0]) {
 690    case TYPE_NULL:
 691        /* no argument */
 692        ret = get_errno(ioctl(fd, ie->host_cmd));
 693        break;
 694    case TYPE_PTRVOID:
 695    case TYPE_INT:
 696        /* int argment */
 697        ret = get_errno(ioctl(fd, ie->host_cmd, arg));
 698        break;
 699    case TYPE_PTR:
 700        arg_type++;
 701        target_size = thunk_type_size(arg_type, 0);
 702        switch(ie->access) {
 703        case IOC_R:
 704            ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
 705            if (!is_error(ret)) {
 706                argptr = lock_user(arg, target_size, 0);
 707                thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
 708                unlock_user(argptr, arg, target_size);
 709            }
 710            break;
 711        case IOC_W:
 712            argptr = lock_user(arg, target_size, 1);
 713            thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
 714            unlock_user(argptr, arg, 0);
 715            ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
 716            break;
 717        default:
 718        case IOC_RW:
 719            argptr = lock_user(arg, target_size, 1);
 720            thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
 721            unlock_user(argptr, arg, 0);
 722            ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
 723            if (!is_error(ret)) {
 724                argptr = lock_user(arg, target_size, 0);
 725                thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
 726                unlock_user(argptr, arg, target_size);
 727            }
 728            break;
 729        }
 730        break;
 731    default:
 732        gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n", cmd, arg_type[0]);
 733        ret = -ENOSYS;
 734        break;
 735    }
 736    return ret;
 737}
 738
 739/* ------------------------------------------------------------
 740   Unix syscall handling
 741*/
 742
 743static inline void byteswap_attrlist(struct attrlist *a)
 744{
 745    tswap16s(&a->bitmapcount);
 746    tswap16s(&a->reserved);
 747    tswap32s(&a->commonattr);
 748    tswap32s(&a->volattr);
 749    tswap32s(&a->dirattr);
 750    tswap32s(&a->fileattr);
 751    tswap32s(&a->forkattr);
 752}
 753
 754struct attrbuf_header {
 755    unsigned long length;
 756};
 757
 758static inline void byteswap_attrbuf(struct attrbuf_header *attrbuf, struct attrlist *attrlist)
 759{
 760    DPRINTF("attrBuf.lenght %lx\n", attrbuf->length);
 761}
 762
 763static inline void byteswap_statfs(struct statfs *s)
 764{
 765    tswap16s((uint16_t*)&s->f_otype);
 766    tswap16s((uint16_t*)&s->f_oflags);
 767    tswap32s((uint32_t*)&s->f_bsize);
 768    tswap32s((uint32_t*)&s->f_iosize);
 769    tswap32s((uint32_t*)&s->f_blocks);
 770    tswap32s((uint32_t*)&s->f_bfree);
 771    tswap32s((uint32_t*)&s->f_bavail);
 772    tswap32s((uint32_t*)&s->f_files);
 773    tswap32s((uint32_t*)&s->f_ffree);
 774    tswap32s((uint32_t*)&s->f_fsid.val[0]);
 775    tswap32s((uint32_t*)&s->f_fsid.val[1]);
 776    tswap16s((uint16_t*)&s->f_reserved1);
 777    tswap16s((uint16_t*)&s->f_type);
 778    tswap32s((uint32_t*)&s->f_flags);
 779}
 780
 781static inline void byteswap_stat(struct stat *s)
 782{
 783    tswap32s((uint32_t*)&s->st_dev);
 784    tswap32s(&s->st_ino);
 785    tswap16s(&s->st_mode);
 786    tswap16s(&s->st_nlink);
 787    tswap32s(&s->st_uid);
 788    tswap32s(&s->st_gid);
 789    tswap32s((uint32_t*)&s->st_rdev);
 790    tswap32s((uint32_t*)&s->st_atimespec.tv_sec);
 791    tswap32s((uint32_t*)&s->st_atimespec.tv_nsec);
 792    tswap32s((uint32_t*)&s->st_mtimespec.tv_sec);
 793    tswap32s((uint32_t*)&s->st_mtimespec.tv_nsec);
 794    tswap32s((uint32_t*)&s->st_ctimespec.tv_sec);
 795    tswap32s((uint32_t*)&s->st_ctimespec.tv_nsec);
 796    tswap64s((uint64_t*)&s->st_size);
 797    tswap64s((uint64_t*)&s->st_blocks);
 798    tswap32s((uint32_t*)&s->st_blksize);
 799    tswap32s(&s->st_flags);
 800    tswap32s(&s->st_gen);
 801}
 802
 803static inline void byteswap_dirents(struct dirent *d, int bytes)
 804{
 805    char *b;
 806    for( b = (char*)d; (int)b < (int)d+bytes; )
 807    {
 808        unsigned short s = ((struct dirent *)b)->d_reclen;
 809        tswap32s(&((struct dirent *)b)->d_ino);
 810        tswap16s(&((struct dirent *)b)->d_reclen);
 811        if(s<=0)
 812            break;
 813        b += s;
 814    }
 815}
 816
 817static inline void byteswap_iovec(struct iovec *v, int n)
 818{
 819    int i;
 820    for(i = 0; i < n; i++)
 821    {
 822        tswap32s((uint32_t*)&v[i].iov_base);
 823        tswap32s((uint32_t*)&v[i].iov_len);
 824    }
 825}
 826
 827static inline void byteswap_timeval(struct timeval *t)
 828{
 829    tswap32s((uint32_t*)&t->tv_sec);
 830    tswap32s((uint32_t*)&t->tv_usec);
 831}
 832
 833long do_unix_syscall_indirect(void *cpu_env, int num);
 834long do_sync(void);
 835long do_exit(uint32_t arg1);
 836long do_getlogin(char *out, uint32_t size);
 837long do_open(char * arg1, uint32_t arg2, uint32_t arg3);
 838long do_getfsstat(struct statfs * arg1, uint32_t arg2, uint32_t arg3);
 839long do_sigprocmask(uint32_t arg1, uint32_t * arg2, uint32_t * arg3);
 840long do_execve(char* arg1, char ** arg2, char ** arg3);
 841long do_getgroups(uint32_t arg1, gid_t * arg2);
 842long do_gettimeofday(struct timeval * arg1, void * arg2);
 843long do_readv(uint32_t arg1, struct iovec * arg2, uint32_t arg3);
 844long do_writev(uint32_t arg1, struct iovec * arg2, uint32_t arg3);
 845long do_utimes(char * arg1, struct timeval * arg2);
 846long do_futimes(uint32_t arg1, struct timeval * arg2);
 847long do_statfs(char * arg1, struct statfs * arg2);
 848long do_fstatfs(uint32_t arg1, struct statfs * arg2);
 849long do_stat(char * arg1, struct stat * arg2);
 850long do_fstat(uint32_t arg1, struct stat * arg2);
 851long do_lstat(char * arg1, struct stat * arg2);
 852long do_getdirentries(uint32_t arg1, void* arg2, uint32_t arg3, void* arg4);
 853long do_lseek(void *cpu_env, int num);
 854long do___sysctl(int * name, uint32_t namelen, void * oldp, size_t * oldlenp, void * newp, size_t newlen  /* ignored */);
 855long do_getattrlist(void * arg1, void * arg2, void * arg3, uint32_t arg4, uint32_t arg5);
 856long do_getdirentriesattr(uint32_t arg1, void * arg2, void * arg3, size_t arg4, void * arg5, void * arg6, void* arg7, uint32_t arg8);
 857long do_fcntl(int fd, int cmd, int arg);
 858
 859long no_syscall(void *cpu_env, int num);
 860
 861long do_pread(uint32_t arg1, void * arg2, size_t arg3, off_t arg4)
 862{
 863    DPRINTF("0x%x, %p, 0x%lx, 0x%llx\n", arg1, arg2, arg3, arg4);
 864    long ret = pread(arg1, arg2, arg3, arg4);
 865    return ret;
 866}
 867
 868long do_read(int d, void *buf, size_t nbytes)
 869{
 870    DPRINTF("0x%x, %p, 0x%lx\n", d, buf, nbytes);
 871    long ret = get_errno(read(d, buf, nbytes));
 872    if(!is_error(ret))
 873        DPRINTF("%x\n", *(uint32_t*)buf);
 874    return ret;
 875}
 876
 877long unimpl_unix_syscall(void *cpu_env, int num);
 878
 879typedef long (*syscall_function_t)(void *cpu_env, int num);
 880
 881
 882/* define a table that will handle the syscall number->function association */
 883#define VOID    void
 884#define INT     (uint32_t)get_int_arg(&i, cpu_env)
 885#define INT64   (uint64_t)get_int64_arg(&i, cpu_env)
 886#define UINT    (unsigned int)INT
 887#define PTR     (void*)INT
 888
 889#define SIZE    INT
 890#define OFFSET  INT64
 891
 892#define WRAPPER_CALL_DIRECT_0(function, args) long __qemu_##function(void *cpu_env) {  return (long)function(); }
 893#define WRAPPER_CALL_DIRECT_1(function, _arg1) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1;  return (long)function(arg1); }
 894#define WRAPPER_CALL_DIRECT_2(function, _arg1, _arg2) long __qemu_##function(void *cpu_env) { int i = 0;  typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; return (long)function(arg1, arg2); }
 895#define WRAPPER_CALL_DIRECT_3(function, _arg1, _arg2, _arg3) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; return (long)function(arg1, arg2, arg3); }
 896#define WRAPPER_CALL_DIRECT_4(function, _arg1, _arg2, _arg3, _arg4) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; return (long)function(arg1, arg2, arg3, arg4); }
 897#define WRAPPER_CALL_DIRECT_5(function, _arg1, _arg2, _arg3, _arg4, _arg5) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5;  return (long)function(arg1, arg2, arg3, arg4, arg5); }
 898#define WRAPPER_CALL_DIRECT_6(function, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; typeof(_arg6) arg6 = _arg6;  return (long)function(arg1, arg2, arg3, arg4, arg5, arg6); }
 899#define WRAPPER_CALL_DIRECT_7(function, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; typeof(_arg6) arg6 = _arg6; typeof(_arg7) arg7 = _arg7; return (long)function(arg1, arg2, arg3, arg4, arg5, arg6, arg7); }
 900#define WRAPPER_CALL_DIRECT_8(function, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7, _arg8) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; typeof(_arg6) arg6 = _arg6; typeof(_arg7) arg7 = _arg7; typeof(_arg8) arg8 = _arg8;  return (long)function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); }
 901#define WRAPPER_CALL_DIRECT(function, nargs, args...) WRAPPER_CALL_DIRECT_##nargs(function, args)
 902#define WRAPPER_CALL_NOERRNO(function, nargs, args...)  WRAPPER_CALL_DIRECT(function, nargs, args)
 903#define WRAPPER_CALL_INDIRECT(function, nargs, args...)
 904#define ENTRY(name, number, function, nargs, call_type, args...)  WRAPPER_##call_type(function, nargs, args)
 905
 906#include "syscalls.h"
 907
 908#undef ENTRY
 909#undef WRAPPER_CALL_DIRECT
 910#undef WRAPPER_CALL_NOERRNO
 911#undef WRAPPER_CALL_INDIRECT
 912#undef OFFSET
 913#undef SIZE
 914#undef INT
 915#undef PTR
 916#undef INT64
 917
 918#define _ENTRY(name, number, function, nargs, call_type) [number] = {\
 919        name, \
 920        number, \
 921        (syscall_function_t)function, \
 922        nargs, \
 923        call_type  \
 924        },
 925
 926#define ENTRY_CALL_DIRECT(name, number, function, nargs, call_type)  _ENTRY(name, number, __qemu_##function, nargs, call_type)
 927#define ENTRY_CALL_NOERRNO(name, number, function, nargs, call_type) ENTRY_CALL_DIRECT(name, number, function, nargs, call_type)
 928#define ENTRY_CALL_INDIRECT(name, number, function, nargs, call_type) _ENTRY(name, number, function, nargs, call_type)
 929#define ENTRY(name, number, function, nargs, call_type, args...) ENTRY_##call_type(name, number, function, nargs, call_type)
 930
 931#define CALL_DIRECT 1
 932#define CALL_INDIRECT 2
 933#define CALL_NOERRNO  (CALL_DIRECT | 4 /* = 5 */)
 934
 935struct unix_syscall {
 936    char * name;
 937    int number;
 938    syscall_function_t function;
 939    int nargs;
 940    int call_type;
 941} unix_syscall_table[SYS_MAXSYSCALL] = {
 942#include "syscalls.h"
 943};
 944
 945#undef ENTRY
 946#undef _ENTRY
 947#undef ENTRY_CALL_DIRECT
 948#undef ENTRY_CALL_INDIRECT
 949#undef ENTRY_CALL_NOERRNO
 950
 951/* Actual syscalls implementation */
 952
 953long do_unix_syscall_indirect(void *cpu_env, int num)
 954{
 955    long ret;
 956    int new_num;
 957    int i = 0;
 958
 959    new_num = get_int_arg(&i, cpu_env);
 960#ifdef TARGET_I386
 961    ((CPUX86State*)cpu_env)->regs[R_ESP] += 4;
 962    /* XXX: not necessary */
 963    ((CPUX86State*)cpu_env)->regs[R_EAX] = new_num;
 964#elif TARGET_PPC
 965    {
 966        int i;
 967        uint32_t **regs = ((CPUPPCState*)cpu_env)->gpr;
 968        for(i = 3; i < 11; i++)
 969            *regs[i] = *regs[i+1];
 970        /* XXX: not necessary */
 971        *regs[0] = new_num;
 972    }
 973#endif
 974    ret = do_unix_syscall(cpu_env, new_num);
 975#ifdef TARGET_I386
 976    ((CPUX86State*)cpu_env)->regs[R_ESP] -= 4;
 977    /* XXX: not necessary */
 978    ((CPUX86State*)cpu_env)->regs[R_EAX] = num;
 979#elif TARGET_PPC
 980    {
 981        int i;
 982        /* XXX: not really needed those regs are volatile accross calls */
 983        uint32_t **regs = ((CPUPPCState*)cpu_env)->gpr;
 984        for(i = 11; i > 3; i--)
 985            *regs[i] = *regs[i-1];
 986        regs[3] = new_num;
 987        *regs[0] = num;
 988    }
 989#endif
 990    return ret;
 991}
 992
 993long do_exit(uint32_t arg1)
 994{
 995    exit(arg1);
 996    /* not reached */
 997    return -1;
 998}
 999
1000long do_sync(void)
1001{
1002    sync();
1003    return 0;
1004}
1005
1006long do_getlogin(char *out, uint32_t size)
1007{
1008    char *login = getlogin();
1009    if(!login)
1010        return -1;
1011    memcpy(out, login, size);
1012    return 0;
1013}
1014long do_open(char * arg1, uint32_t arg2, uint32_t arg3)
1015{
1016    /* XXX: don't let the %s stay in there */
1017    DPRINTF("open(%s, 0x%x, 0x%x)\n", arg1, arg2, arg3);
1018    return get_errno(open(arg1, arg2, arg3));
1019}
1020
1021long do_getfsstat(struct statfs * arg1, uint32_t arg2, uint32_t arg3)
1022{
1023    long ret;
1024    DPRINTF("getfsstat(%p, 0x%x, 0x%x)\n", arg1, arg2, arg3);
1025    ret = get_errno(getfsstat(arg1, arg2, arg3));
1026    if((!is_error(ret)) && arg1)
1027        byteswap_statfs(arg1);
1028    return ret;
1029}
1030
1031long do_sigprocmask(uint32_t arg1, uint32_t * arg2, uint32_t * arg3)
1032{
1033    long ret;
1034    DPRINTF("sigprocmask(%d, %p, %p)\n", arg1, arg2, arg3);
1035    gemu_log("XXX: sigprocmask not tested (%d, %p, %p)\n", arg1, arg2, arg3);
1036    if(arg2)
1037        tswap32s(arg2);
1038    ret = get_errno(sigprocmask(arg1, (void *)arg2, (void *)arg3));
1039    if((!is_error(ret)) && arg3)
1040        tswap32s(arg3);
1041    if(arg2)
1042        tswap32s(arg2);
1043    return ret;
1044}
1045
1046long do_execve(char* arg1, char ** arg2, char ** arg3)
1047{
1048    long ret;
1049    char **argv = arg2;
1050    char **envp = arg3;
1051    int argc;
1052    int envc;
1053
1054    /* XXX: don't let the %s stay in here */
1055    DPRINTF("execve(%s, %p, %p)\n", arg1, arg2, arg3);
1056
1057    for(argc = 0; argv[argc]; argc++);
1058    for(envc = 0; envp[envc]; envc++);
1059
1060    argv = (char**)malloc(sizeof(char*)*argc);
1061    envp = (char**)malloc(sizeof(char*)*envc);
1062
1063    for(; argc >= 0; argc--)
1064        argv[argc] = (char*)tswap32((uint32_t)(arg2)[argc]);
1065
1066    for(; envc >= 0; envc--)
1067        envp[envc] = (char*)tswap32((uint32_t)(arg3)[envc]);
1068
1069    ret = get_errno(execve(arg1, argv, envp));
1070    free(argv);
1071    free(envp);
1072    return ret;
1073}
1074
1075long do_getgroups(uint32_t arg1, gid_t * arg2)
1076{
1077    long ret;
1078    int i;
1079    DPRINTF("getgroups(0x%x, %p)\n", arg1, arg2);
1080    ret = get_errno(getgroups(arg1, arg2));
1081    if(ret > 0)
1082        for(i = 0; i < arg1; i++)
1083            tswap32s(&arg2[i]);
1084    return ret;
1085}
1086
1087long do_gettimeofday(struct timeval * arg1, void * arg2)
1088{
1089    long ret;
1090    DPRINTF("gettimeofday(%p, %p)\n",
1091            arg1, arg2);
1092    ret = get_errno(gettimeofday(arg1, arg2));
1093    if(!is_error(ret))
1094    {
1095        /* timezone no longer used according to the manpage, so don't bother with it */
1096        byteswap_timeval(arg1);
1097    }
1098    return ret;
1099}
1100
1101long do_readv(uint32_t arg1, struct iovec * arg2, uint32_t arg3)
1102{
1103    long ret;
1104    DPRINTF("readv(0x%x, %p, 0x%x)\n", arg1, arg2, arg3);
1105    if(arg2)
1106        byteswap_iovec(arg2, arg3);
1107    ret = get_errno(readv(arg1, arg2, arg3));
1108    if((!is_error(ret)) && arg2)
1109        byteswap_iovec(arg2, arg3);
1110    return ret;
1111}
1112
1113long do_writev(uint32_t arg1, struct iovec * arg2, uint32_t arg3)
1114{
1115    long ret;
1116    DPRINTF("writev(0x%x, %p, 0x%x)\n", arg1, arg2, arg3);
1117    if(arg2)
1118        byteswap_iovec(arg2, arg3);
1119    ret = get_errno(writev(arg1, arg2, arg3));
1120    if((!is_error(ret)) && arg2)
1121        byteswap_iovec(arg2, arg3);
1122    return ret;
1123}
1124
1125long do_utimes(char * arg1, struct timeval * arg2)
1126{
1127    DPRINTF("utimes(%p, %p)\n", arg1, arg2);
1128    if(arg2)
1129    {
1130        byteswap_timeval(arg2);
1131        byteswap_timeval(arg2+1);
1132    }
1133    return get_errno(utimes(arg1, arg2));
1134}
1135
1136long do_futimes(uint32_t arg1, struct timeval * arg2)
1137{
1138    DPRINTF("futimes(0x%x, %p)\n", arg1, arg2);
1139    if(arg2)
1140    {
1141        byteswap_timeval(arg2);
1142        byteswap_timeval(arg2+1);
1143    }
1144    return get_errno(futimes(arg1, arg2));
1145}
1146
1147long do_statfs(char * arg1, struct statfs * arg2)
1148{
1149    long ret;
1150    DPRINTF("statfs(%p, %p)\n", arg1, arg2);
1151    ret = get_errno(statfs(arg1, arg2));
1152    if(!is_error(ret))
1153        byteswap_statfs(arg2);
1154    return ret;
1155}
1156
1157long do_fstatfs(uint32_t arg1, struct statfs* arg2)
1158{
1159    long ret;
1160    DPRINTF("fstatfs(0x%x, %p)\n",
1161            arg1, arg2);
1162    ret = get_errno(fstatfs(arg1, arg2));
1163    if(!is_error(ret))
1164        byteswap_statfs(arg2);
1165
1166    return ret;
1167}
1168
1169long do_stat(char * arg1, struct stat * arg2)
1170{
1171    long ret;
1172    /* XXX: don't let the %s stay in there */
1173    DPRINTF("stat(%s, %p)\n", arg1, arg2);
1174    ret = get_errno(stat(arg1, arg2));
1175    if(!is_error(ret))
1176        byteswap_stat(arg2);
1177    return ret;
1178}
1179
1180long do_fstat(uint32_t arg1, struct stat * arg2)
1181{
1182    long ret;
1183    DPRINTF("fstat(0x%x, %p)\n", arg1, arg2);
1184    ret = get_errno(fstat(arg1, arg2));
1185    if(!is_error(ret))
1186        byteswap_stat(arg2);
1187    return ret;
1188}
1189
1190long do_lstat(char * arg1, struct stat * arg2)
1191{
1192    long ret;
1193    /* XXX: don't let the %s stay in there */
1194    DPRINTF("lstat(%s, %p)\n", (const char *)arg1, arg2);
1195    ret = get_errno(lstat(arg1, arg2));
1196    if(!is_error(ret))
1197        byteswap_stat(arg2);
1198    return ret;
1199}
1200
1201long do_getdirentries(uint32_t arg1, void* arg2, uint32_t arg3, void* arg4)
1202{
1203    long ret;
1204    DPRINTF("getdirentries(0x%x, %p, 0x%x, %p)\n", arg1, arg2, arg3, arg4);
1205    if(arg4)
1206        tswap32s((uint32_t *)arg4);
1207    ret = get_errno(getdirentries(arg1, arg2, arg3, arg4));
1208    if(arg4)
1209        tswap32s((uint32_t *)arg4);
1210    if(!is_error(ret))
1211        byteswap_dirents(arg2, ret);
1212    return ret;
1213}
1214
1215long do_lseek(void *cpu_env, int num)
1216{
1217    long ret;
1218    int i = 0;
1219    uint32_t arg1 = get_int_arg(&i, cpu_env);
1220    uint64_t offset = get_int64_arg(&i, cpu_env);
1221    uint32_t arg3 = get_int_arg(&i, cpu_env);
1222    uint64_t r = lseek(arg1, offset, arg3);
1223#ifdef TARGET_I386
1224    /* lowest word in eax, highest in edx */
1225    ret = r & 0xffffffff; /* will be set to eax after do_unix_syscall exit */
1226    ((CPUX86State *)cpu_env)->regs[R_EDX] = (uint32_t)((r >> 32) & 0xffffffff) ;
1227#elif defined TARGET_PPC
1228    ret = r & 0xffffffff; /* will be set to r3 after do_unix_syscall exit */
1229    ((CPUPPCState *)cpu_env)->gpr[4] = (uint32_t)((r >> 32) & 0xffffffff) ;
1230#else
1231    qerror("64 bit ret value on your arch?");
1232#endif
1233    return get_errno(ret);
1234}
1235
1236void no_swap(void * oldp, int size)
1237{
1238}
1239
1240void sysctl_tswap32s(void * oldp, int size)
1241{
1242    tswap32s(oldp);
1243}
1244
1245void bswap_oid(uint32_t * oldp, int size)
1246{
1247    int count = size / sizeof(int);
1248    int i = 0;
1249    do { tswap32s(oldp + i); } while (++i < count);
1250}
1251
1252void sysctl_usrstack(uint32_t * oldp, int size)
1253{
1254    DPRINTF("sysctl_usrstack: 0x%x\n", *oldp);
1255    tswap32s(oldp);
1256}
1257
1258void sysctl_ncpu(uint32_t * ncpu, int size)
1259{
1260    *ncpu = 0x1;
1261    DPRINTF("sysctl_ncpu: 0x%x\n", *ncpu);
1262    tswap32s(ncpu);
1263}
1264
1265void sysctl_exec(char * exec, int size)
1266{
1267    DPRINTF("sysctl_exec: %s\n", exec);
1268}
1269
1270void sysctl_translate(char * exec, int size)
1271{
1272    DPRINTF("sysctl_translate: %s\n", exec);
1273}
1274
1275struct sysctl_dir {
1276    int num;
1277    const char * name;
1278    void (*swap_func)(void *, int);
1279    struct sysctl_dir *childs;
1280};
1281
1282#define ENTRYD(num, name, childs) { num, name, NULL, childs }
1283#define ENTRYE(num, name, func)   { num, name, (void (*)(void *, int))func, NULL  }
1284struct sysctl_dir sysctls_unspec[] = {
1285    ENTRYE(3,  "oip", bswap_oid),
1286    { 0, NULL, NULL, NULL }
1287};
1288
1289struct sysctl_dir sysctls_kern[] = {
1290    ENTRYE(KERN_TRANSLATE,          "translate",    sysctl_translate), /* 44 */
1291    ENTRYE(KERN_EXEC,               "exec",         sysctl_exec), /* 45 */
1292    ENTRYE(KERN_USRSTACK32,          "KERN_USRSTACK32", sysctl_usrstack), /* 35 */
1293    ENTRYE(KERN_SHREG_PRIVATIZABLE,  "KERN_SHREG_PRIVATIZABLE", sysctl_tswap32s), /* 54 */
1294    { 0, NULL, NULL, NULL }
1295};
1296
1297struct sysctl_dir sysctls_hw[] = {
1298    ENTRYE(HW_NCPU, "ncpud", sysctl_tswap32s),
1299    ENTRYE(104, "104", no_swap),
1300    ENTRYE(105, "105", no_swap),
1301    { 0, NULL, NULL, NULL }
1302};
1303
1304struct sysctl_dir sysctls[] = {
1305    ENTRYD(CTL_UNSPEC, "unspec", sysctls_unspec),
1306    ENTRYD(CTL_KERN, "kern", sysctls_kern),
1307    ENTRYD(CTL_HW,   "hw",   sysctls_hw ),
1308    { 0, NULL, NULL, NULL }
1309};
1310
1311#undef ENTRYE
1312#undef ENTRYD
1313
1314static inline struct sysctl_dir * get_sysctl_entry_for_mib(int mib, struct sysctl_dir * sysctl_elmt)
1315{
1316    if(!sysctl_elmt)
1317        return NULL;
1318    for(; sysctl_elmt->name != NULL ; sysctl_elmt++) {
1319        if(sysctl_elmt->num == mib)
1320            return sysctl_elmt;
1321    }
1322    return NULL;
1323}
1324
1325static inline long bswap_syctl(int * mib, int count, void *buf, int size)
1326{
1327    int i;
1328    struct sysctl_dir * sysctl = sysctls;
1329    struct sysctl_dir * ret = NULL;
1330
1331    for(i = 0; i < count; i++) {
1332
1333        if(!(ret = sysctl = get_sysctl_entry_for_mib(mib[i], sysctl))) {
1334            gemu_log("bswap_syctl: can't find mib %d\n", mib[i]);
1335            return -ENOTDIR;
1336        }
1337        if(!(sysctl = sysctl->childs))
1338            break;
1339    }
1340
1341    if(ret->childs)
1342        qerror("we shouldn't have a directory element\n");
1343
1344    ret->swap_func(buf, size);
1345    return 0;
1346}
1347
1348static inline void print_syctl(int * mib, int count)
1349{
1350    int i;
1351    struct sysctl_dir * sysctl = sysctls;
1352    struct sysctl_dir * ret = NULL;
1353
1354    for(i = 0; i < count; i++) {
1355        if(!(ret = sysctl = get_sysctl_entry_for_mib(mib[i], sysctl))){
1356            gemu_log("print_syctl: can't find mib %d\n", mib[i]);
1357            return;
1358        }
1359        DPRINTF("%s.", sysctl->name);
1360        if(!(sysctl = sysctl->childs))
1361            break;
1362    }
1363    DPRINTF("\n");
1364}
1365
1366long do___sysctl(int * name, uint32_t namelen, void * oldp, size_t * oldlenp, void * newp, size_t newlen  /* ignored */)
1367{
1368    long ret = 0;
1369    int i;
1370    DPRINTF("sysctl(%p, 0x%x, %p, %p, %p, 0x%lx)\n",
1371            name, namelen, oldp, oldlenp, newp, newlen);
1372    if(name) {
1373        i = 0;
1374        do { tswap32s( name + i); } while (++i < namelen);
1375        print_syctl(name, namelen);
1376        //bswap_syctl(name, namelen, newp, newlen);
1377        tswap32s((uint32_t*)oldlenp);
1378    }
1379
1380    if(name) /* Sometimes sysctl is called with no arg1, ignore */
1381        ret = get_errno(sysctl(name, namelen, oldp, oldlenp, newp, newlen));
1382
1383#if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__)
1384    if (!is_error(ret) && bswap_syctl(name, namelen, oldp, *oldlenp) != 0) {
1385        return -ENOTDIR;
1386    }
1387#endif
1388
1389    if(name) {
1390        //bswap_syctl(name, namelen, newp, newlen);
1391        tswap32s((uint32_t*)oldlenp);
1392
1393        i = 0;
1394        do { tswap32s( name + i); } while (++i < namelen);
1395    }
1396    return ret;
1397}
1398
1399long do_getattrlist(void * arg1, void * arg2, void * arg3, uint32_t arg4, uint32_t arg5)
1400{
1401    struct attrlist * attrlist = (void *)arg2;
1402    long ret;
1403
1404#if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__)
1405    gemu_log("SYS_getdirentriesattr unimplemented\n");
1406    return -ENOTSUP;
1407#endif
1408    /* XXX: don't let the %s stay in there */
1409    DPRINTF("getattrlist(%s, %p, %p, 0x%x, 0x%x)\n",
1410            (char *)arg1, arg2, arg3, arg4, arg5);
1411
1412    if(arg2) /* XXX: We should handle that in a copy especially
1413        if the structure is not writable */
1414        byteswap_attrlist(attrlist);
1415
1416    ret = get_errno(getattrlist((const char* )arg1, attrlist, (void *)arg3, arg4, arg5));
1417
1418    if(!is_error(ret))
1419    {
1420        byteswap_attrbuf((void *)arg3, attrlist);
1421        byteswap_attrlist(attrlist);
1422    }
1423    return ret;
1424}
1425
1426long do_getdirentriesattr(uint32_t arg1, void * arg2, void * arg3, size_t arg4, void * arg5, void * arg6, void* arg7, uint32_t arg8)
1427{
1428    DPRINTF("getdirentriesattr(0x%x, %p, %p, 0x%lx, %p, %p, %p, 0x%x)\n",
1429            arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
1430#if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__)
1431    qerror("SYS_getdirentriesattr unimplemented\n");
1432#endif
1433
1434    return get_errno(getdirentriesattr( arg1, (struct attrlist * )arg2, (void *)arg3, arg4,
1435                                       (unsigned long *)arg5, (unsigned long *)arg6,
1436                                       (unsigned long *)arg7, arg8));
1437}
1438
1439static inline void bswap_flock(struct flock *f)
1440{
1441    tswap64s(&f->l_start);
1442    tswap64s(&f->l_len);
1443    tswap32s(&f->l_pid);
1444    tswap16s(&f->l_type);
1445    tswap16s(&f->l_whence);
1446}
1447
1448static inline void bswap_fstore(struct fstore *f)
1449{
1450    tswap32s(&f->fst_flags);
1451    tswap32s(&f->fst_posmode);
1452    tswap64s(&f->fst_offset);
1453    tswap64s(&f->fst_length);
1454    tswap64s(&f->fst_bytesalloc);
1455}
1456
1457static inline void bswap_radvisory(struct radvisory *f)
1458{
1459    tswap64s(&f->ra_offset);
1460    tswap32s(&f->ra_count);
1461}
1462
1463static inline void bswap_fbootstraptransfer(struct fbootstraptransfer *f)
1464{
1465    tswap64s(&f->fbt_offset);
1466    tswap32s((uint32_t*)&f->fbt_length);
1467    tswap32s((uint32_t*)&f->fbt_buffer); /* XXX: this is a ptr */
1468}
1469
1470static inline void bswap_log2phys(struct log2phys *f)
1471{
1472    tswap32s(&f->l2p_flags);
1473    tswap64s(&f->l2p_contigbytes);
1474    tswap64s(&f->l2p_devoffset);
1475}
1476
1477static inline void bswap_fcntl_arg(int cmd, void * arg)
1478{
1479    switch(cmd)
1480    {
1481        case F_DUPFD:
1482        case F_GETFD:
1483        case F_SETFD:
1484        case F_GETFL:
1485        case F_SETFL:
1486        case F_GETOWN:
1487        case F_SETOWN:
1488        case F_SETSIZE:
1489        case F_RDAHEAD:
1490        case F_FULLFSYNC:
1491            break;
1492        case F_GETLK:
1493        case F_SETLK:
1494        case F_SETLKW:
1495            bswap_flock(arg);
1496            break;
1497        case F_PREALLOCATE:
1498            bswap_fstore(arg);
1499            break;
1500        case F_RDADVISE:
1501            bswap_radvisory(arg);
1502            break;
1503        case F_READBOOTSTRAP:
1504        case F_WRITEBOOTSTRAP:
1505            bswap_fbootstraptransfer(arg);
1506            break;
1507        case F_LOG2PHYS:
1508            bswap_log2phys(arg);
1509            break;
1510        default:
1511            gemu_log("unknow cmd in fcntl\n");
1512    }
1513}
1514
1515long do_fcntl(int fd, int cmd, int arg)
1516{
1517    long ret;
1518    bswap_fcntl_arg(cmd, (void *)arg);
1519    ret = get_errno(fcntl(fd, cmd, arg));
1520    if(!is_error(ret))
1521        bswap_fcntl_arg(cmd, (void *)arg);
1522    return ret;
1523}
1524
1525long no_syscall(void *cpu_env, int num)
1526{
1527    /* XXX: We should probably fordward it to the host kernel */
1528    qerror("no unix syscall %d\n", num);
1529    /* not reached */
1530    return -1;
1531}
1532
1533long unimpl_unix_syscall(void *cpu_env, int num)
1534{
1535    if( (num < 0) || (num > SYS_MAXSYSCALL-1) )
1536        qerror("unix syscall %d is out of unix syscall bounds (0-%d) " , num, SYS_MAXSYSCALL-1);
1537
1538    gemu_log("qemu: Unsupported unix syscall %s %d\n", unix_syscall_table[num].name , num);
1539    gdb_handlesig (cpu_env, SIGTRAP);
1540    exit(-1);
1541}
1542
1543long do_unix_syscall(void *cpu_env, int num)
1544{
1545    long ret = 0;
1546
1547    DPRINTF("unix syscall %d: " , num);
1548
1549    if( (num < 0) || (num > SYS_MAXSYSCALL-1) )
1550        qerror("unix syscall %d is out of unix syscall bounds (0-%d) " , num, SYS_MAXSYSCALL-1);
1551
1552    DPRINTF("%s [%s]", unix_syscall_table[num].name, unix_syscall_table[num].call_type & CALL_DIRECT ? "direct" : "indirect" );
1553    ret = unix_syscall_table[num].function(cpu_env, num);
1554
1555    if(!(unix_syscall_table[num].call_type & CALL_NOERRNO))
1556        ret = get_errno(ret);
1557
1558    DPRINTF("[returned 0x%x(%d)]\n", (int)ret, (int)ret);
1559    return ret;
1560}
1561
1562/* ------------------------------------------------------------
1563   syscall_init
1564*/
1565void syscall_init(void)
1566{
1567    /* Nothing yet */
1568}
1569