(linenum→info "unix/slp.c:2238")

qemu/0.9.1/linux-user/strace.c

    1: #include <stdio.h>
    2: #include <errno.h>
    3: #include <sys/ipc.h>
    4: #include <sys/msg.h>
    5: #include <sys/sem.h>
    6: #include <sys/shm.h>
    7: #include <sys/select.h>
    8: #include <sys/types.h>
    9: #include <unistd.h>
   10: #include "qemu.h"
   11: 
   12: int do_strace=0;
   13: 
   14: struct syscallname {
   15:     int nr;
   16:     char *name;
   17:     char *format;
   18:     void (*call)(struct syscallname *,
   19:                  abi_long, abi_long, abi_long,
   20:                  abi_long, abi_long, abi_long);
   21:     void (*result)(struct syscallname *, abi_long);
   22: };
   23: 
   24: /*
   25:  * Utility functions
   26:  */
   27: static void
   28: print_ipc_cmd(int cmd)
   29: {
   30: #define output_cmd(val) \
   31: if( cmd == val ) { \
   32:     gemu_log(#val); \
   33:     return; \
   34: }
   35: 
   36:     cmd &= 0xff;
   37: 
   38:     /* General IPC commands */
   39:     output_cmd( IPC_RMID );
   40:     output_cmd( IPC_SET );
   41:     output_cmd( IPC_STAT );
   42:     output_cmd( IPC_INFO );
   43:     /* msgctl() commands */
   44:     #ifdef __USER_MISC
   45:     output_cmd( MSG_STAT );
   46:     output_cmd( MSG_INFO );
   47:     #endif
   48:     /* shmctl() commands */
   49:     output_cmd( SHM_LOCK );
   50:     output_cmd( SHM_UNLOCK );
   51:     output_cmd( SHM_STAT );
   52:     output_cmd( SHM_INFO );
   53:     /* semctl() commands */
   54:     output_cmd( GETPID );
   55:     output_cmd( GETVAL );
   56:     output_cmd( GETALL );
   57:     output_cmd( GETNCNT );
   58:     output_cmd( GETZCNT );
   59:     output_cmd( SETVAL );
   60:     output_cmd( SETALL );
   61:     output_cmd( SEM_STAT );
   62:     output_cmd( SEM_INFO );
   63:     output_cmd( IPC_RMID );
   64:     output_cmd( IPC_RMID );
   65:     output_cmd( IPC_RMID );
   66:     output_cmd( IPC_RMID );
   67:     output_cmd( IPC_RMID );
   68:     output_cmd( IPC_RMID );
   69:     output_cmd( IPC_RMID );
   70:     output_cmd( IPC_RMID );
   71:     output_cmd( IPC_RMID );
   72: 
   73:     /* Some value we don't recognize */
   74:     gemu_log("%d",cmd);
   75: }
   76: 
   77: #ifdef TARGET_NR__newselect
   78: static void
   79: print_fdset(int n, abi_ulong target_fds_addr)
   80: {
   81:     int i;
   82: 
   83:     gemu_log("[");
   84:     if( target_fds_addr ) {
   85:         abi_long *target_fds;
   86: 
   87:         target_fds = lock_user(VERIFY_READ,
   88:                                target_fds_addr,
   89:                                sizeof(*target_fds)*(n / TARGET_ABI_BITS + 1),
   90:                                1);
   91: 
   92:         if (!target_fds)
   93:             return;
   94: 
   95:         for (i=n; i>=0; i--) {
   96:             if ((tswapl(target_fds[i / TARGET_ABI_BITS]) >> (i & (TARGET_ABI_BITS - 1))) & 1)
   97:                 gemu_log("%d,", i );
   98:             }
   99:         unlock_user(target_fds, target_fds_addr, 0);
  100:     }
  101:     gemu_log("]");
  102: }
  103: 
  104: static void
  105: print_timeval(abi_ulong tv_addr)
  106: {
  107:     if( tv_addr ) {
  108:         struct target_timeval *tv;
  109: 
  110:         tv = lock_user(VERIFY_READ, tv_addr, sizeof(*tv), 1);
  111:         if (!tv)
  112:             return;
  113:         gemu_log("{" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "}",
  114:                  tv->tv_sec, tv->tv_usec);
  115:         unlock_user(tv, tv_addr, 0);
  116:     } else
  117:         gemu_log("NULL");
  118: }
  119: #endif
  120: 
  121: /*
  122:  * Sysycall specific output functions
  123:  */
  124: 
  125: /* select */
  126: #ifdef TARGET_NR__newselect
  127: static long newselect_arg1 = 0;
  128: static long newselect_arg2 = 0;
  129: static long newselect_arg3 = 0;
  130: static long newselect_arg4 = 0;
  131: static long newselect_arg5 = 0;
  132: 
  133: static void
  134: print_newselect(struct syscallname *name,
  135:                 abi_long arg1, abi_long arg2, abi_long arg3,
  136:                 abi_long arg4, abi_long arg5, abi_long arg6)
  137: {
  138:     gemu_log("%s(" TARGET_ABI_FMT_ld ",", name->name, arg1);
  139:     print_fdset(arg1, arg2);
  140:     gemu_log(",");
  141:     print_fdset(arg1, arg3);
  142:     gemu_log(",");
  143:     print_fdset(arg1, arg4);
  144:     gemu_log(",");
  145:     print_timeval(arg5);
  146:     gemu_log(")");
  147: 
  148:     /* save for use in the return output function below */
  149:     newselect_arg1=arg1;
  150:     newselect_arg2=arg2;
  151:     newselect_arg3=arg3;
  152:     newselect_arg4=arg4;
  153:     newselect_arg5=arg5;
  154: }
  155: #endif
  156: 
  157: static void
  158: print_semctl(struct syscallname *name,
  159:              abi_long arg1, abi_long arg2, abi_long arg3,
  160:              abi_long arg4, abi_long arg5, abi_long arg6)
  161: {
  162:     gemu_log("%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ",", name->name, arg1, arg2);
  163:     print_ipc_cmd(arg3);
  164:     gemu_log(",0x" TARGET_ABI_FMT_lx ")", arg4);
  165: }
  166: 
  167: static void
  168: print_execve(struct syscallname *name,
  169:              abi_long arg1, abi_long arg2, abi_long arg3,
  170:              abi_long arg4, abi_long arg5, abi_long arg6)
  171: {
  172:     abi_ulong arg_ptr_addr;
  173:     char *s;
  174: 
  175:     if (!(s = lock_user_string(arg1)))
  176:         return;
  177:     gemu_log("%s(\"%s\",{", name->name, s);
  178:     unlock_user(s, arg1, 0);
  179: 
  180:     for (arg_ptr_addr = arg2; ; arg_ptr_addr += sizeof(abi_ulong)) {
  181:         abi_ulong *arg_ptr, arg_addr, s_addr;
  182: 
  183:         arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(abi_ulong), 1);
  184:         if (!arg_ptr)
  185:             return;
  186:         arg_addr = tswapl(*arg_ptr);
  187:         unlock_user(arg_ptr, arg_ptr_addr, 0);
  188:         if (!arg_addr)
  189:             break;
  190:         if ((s = lock_user_string(arg_addr))) {
  191:             gemu_log("\"%s\",", s);
  192:             unlock_user(s, s_addr, 0);
  193:         }
  194:     }
  195: 
  196:     gemu_log("NULL})");
  197: }
  198: 
  199: #ifdef TARGET_NR_ipc
  200: static void
  201: print_ipc(struct syscallname *name,
  202:           abi_long arg1, abi_long arg2, abi_long arg3,
  203:           abi_long arg4, abi_long arg5, abi_long arg6)
  204: {
  205:     switch(arg1) {
  206:     case IPCOP_semctl:
  207:         name->name = "semctl";
  208:         print_semctl(name,arg2,arg3,arg4,arg5,arg6,0);
  209:         break;
  210:     default:
  211:         gemu_log("%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ")",
  212:                  name->name, arg1, arg2, arg3, arg4);
  213:     }
  214: }
  215: #endif
  216: 
  217: /*
  218:  * Variants for the return value output function
  219:  */
  220: 
  221: static void
  222: print_syscall_ret_addr(struct syscallname *name, abi_long ret)
  223: {
  224: if( ret == -1 ) {
  225:         gemu_log(" = -1 errno=%d (%s)\n", errno, target_strerror(errno));
  226:     } else {
  227:         gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret);
  228:     }
  229: }
  230: 
  231: #if 0 /* currently unused */
  232: static void
  233: print_syscall_ret_raw(struct syscallname *name, abi_long ret)
  234: {
  235:         gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret);
  236: }
  237: #endif
  238: 
  239: #ifdef TARGET_NR__newselect
  240: static void
  241: print_syscall_ret_newselect(struct syscallname *name, abi_long ret)
  242: {
  243:     gemu_log(" = 0x" TARGET_ABI_FMT_lx " (", ret);
  244:     print_fdset(newselect_arg1,newselect_arg2);
  245:     gemu_log(",");
  246:     print_fdset(newselect_arg1,newselect_arg3);
  247:     gemu_log(",");
  248:     print_fdset(newselect_arg1,newselect_arg4);
  249:     gemu_log(",");
  250:     print_timeval(newselect_arg5);
  251:     gemu_log(")\n");
  252: }
  253: #endif
  254: 
  255: /*
  256:  * An array of all of the syscalls we know about
  257:  */
  258: 
  259: static struct syscallname scnames[] = {
  260: #include "strace.list"
  261: };
  262: 
  263: static int nsyscalls = sizeof(scnames)/sizeof(struct syscallname);
  264: 
  265: /*
  266:  * The public interface to this module.
  267:  */
  268: void
  269: print_syscall(int num,
  270:               abi_long arg1, abi_long arg2, abi_long arg3,
  271:               abi_long arg4, abi_long arg5, abi_long arg6)
  272: {
  273:     int i;
  274:     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 ")";
  275: 
  276:     gemu_log("%d ", getpid() );
  277: 
  278:     for(i=0;i<nsyscalls;i++)
  279:         if( scnames[i].nr == num ) {
  280:             if( scnames[i].call != NULL ) {
  281:                 scnames[i].call(&scnames[i],arg1,arg2,arg3,arg4,arg5,arg6);
  282:             } else {
  283:                 /* XXX: this format system is broken because it uses
  284:                    host types and host pointers for strings */
  285:                 if( scnames[i].format != NULL )
  286:                     format = scnames[i].format;
  287:                 gemu_log(format,scnames[i].name, arg1,arg2,arg3,arg4,arg5,arg6);
  288:             }
  289:             break;
  290:         }
  291: }
  292: 
  293: 
  294: void
  295: print_syscall_ret(int num, abi_long ret)
  296: {
  297:     int i;
  298: 
  299:     for(i=0;i<nsyscalls;i++)
  300:         if( scnames[i].nr == num ) {
  301:             if( scnames[i].result != NULL ) {
  302:                 scnames[i].result(&scnames[i],ret);
  303:             } else {
  304:                 if( ret < 0 ) {
  305:                     gemu_log(" = -1 errno=" TARGET_ABI_FMT_ld " (%s)\n", -ret, target_strerror(-ret));
  306:                 } else {
  307:                     gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret);
  308:                 }
  309:             }
  310:             break;
  311:         }
  312: }
  313: 
Syntax (Markdown)