Annotation of qemu/linux-user/strace.c, revision 1.1.1.2

1.1       root        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;
1.1.1.2 ! root       16:     const char *name;
        !            17:     const char *format;
        !            18:     void (*call)(const struct syscallname *,
1.1       root       19:                  abi_long, abi_long, abi_long,
                     20:                  abi_long, abi_long, abi_long);
1.1.1.2 ! root       21:     void (*result)(const struct syscallname *, abi_long);
1.1       root       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
1.1.1.2 ! root      134: print_newselect(const struct syscallname *name,
1.1       root      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: 
1.1.1.2 ! root      157: #ifdef TARGET_NR_semctl
1.1       root      158: static void
1.1.1.2 ! root      159: print_semctl(const struct syscallname *name,
1.1       root      160:              abi_long arg1, abi_long arg2, abi_long arg3,
                    161:              abi_long arg4, abi_long arg5, abi_long arg6)
                    162: {
                    163:     gemu_log("%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ",", name->name, arg1, arg2);
                    164:     print_ipc_cmd(arg3);
                    165:     gemu_log(",0x" TARGET_ABI_FMT_lx ")", arg4);
                    166: }
1.1.1.2 ! root      167: #endif
1.1       root      168: 
                    169: static void
1.1.1.2 ! root      170: print_execve(const struct syscallname *name,
1.1       root      171:              abi_long arg1, abi_long arg2, abi_long arg3,
                    172:              abi_long arg4, abi_long arg5, abi_long arg6)
                    173: {
                    174:     abi_ulong arg_ptr_addr;
                    175:     char *s;
                    176: 
                    177:     if (!(s = lock_user_string(arg1)))
                    178:         return;
                    179:     gemu_log("%s(\"%s\",{", name->name, s);
                    180:     unlock_user(s, arg1, 0);
                    181: 
                    182:     for (arg_ptr_addr = arg2; ; arg_ptr_addr += sizeof(abi_ulong)) {
1.1.1.2 ! root      183:         abi_ulong *arg_ptr, arg_addr;
1.1       root      184: 
                    185:        arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(abi_ulong), 1);
                    186:         if (!arg_ptr)
                    187:             return;
                    188:        arg_addr = tswapl(*arg_ptr);
                    189:        unlock_user(arg_ptr, arg_ptr_addr, 0);
                    190:         if (!arg_addr)
                    191:             break;
                    192:         if ((s = lock_user_string(arg_addr))) {
                    193:             gemu_log("\"%s\",", s);
1.1.1.2 ! root      194:             unlock_user(s, arg_addr, 0);
1.1       root      195:         }
                    196:     }
                    197: 
                    198:     gemu_log("NULL})");
                    199: }
                    200: 
                    201: #ifdef TARGET_NR_ipc
                    202: static void
1.1.1.2 ! root      203: print_ipc(const struct syscallname *name,
1.1       root      204:           abi_long arg1, abi_long arg2, abi_long arg3,
                    205:           abi_long arg4, abi_long arg5, abi_long arg6)
                    206: {
                    207:     switch(arg1) {
                    208:     case IPCOP_semctl:
1.1.1.2 ! root      209:         gemu_log("semctl(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ",", arg1, arg2);
        !           210:         print_ipc_cmd(arg3);
        !           211:         gemu_log(",0x" TARGET_ABI_FMT_lx ")", arg4);
1.1       root      212:         break;
                    213:     default:
                    214:         gemu_log("%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ")",
                    215:                  name->name, arg1, arg2, arg3, arg4);
                    216:     }
                    217: }
                    218: #endif
                    219: 
                    220: /*
                    221:  * Variants for the return value output function
                    222:  */
                    223: 
                    224: static void
1.1.1.2 ! root      225: print_syscall_ret_addr(const struct syscallname *name, abi_long ret)
1.1       root      226: {
                    227: if( ret == -1 ) {
                    228:         gemu_log(" = -1 errno=%d (%s)\n", errno, target_strerror(errno));
                    229:     } else {
                    230:         gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret);
                    231:     }
                    232: }
                    233: 
                    234: #if 0 /* currently unused */
                    235: static void
                    236: print_syscall_ret_raw(struct syscallname *name, abi_long ret)
                    237: {
                    238:         gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret);
                    239: }
                    240: #endif
                    241: 
                    242: #ifdef TARGET_NR__newselect
                    243: static void
1.1.1.2 ! root      244: print_syscall_ret_newselect(const struct syscallname *name, abi_long ret)
1.1       root      245: {
                    246:     gemu_log(" = 0x" TARGET_ABI_FMT_lx " (", ret);
                    247:     print_fdset(newselect_arg1,newselect_arg2);
                    248:     gemu_log(",");
                    249:     print_fdset(newselect_arg1,newselect_arg3);
                    250:     gemu_log(",");
                    251:     print_fdset(newselect_arg1,newselect_arg4);
                    252:     gemu_log(",");
                    253:     print_timeval(newselect_arg5);
                    254:     gemu_log(")\n");
                    255: }
                    256: #endif
                    257: 
                    258: /*
                    259:  * An array of all of the syscalls we know about
                    260:  */
                    261: 
1.1.1.2 ! root      262: static const struct syscallname scnames[] = {
1.1       root      263: #include "strace.list"
                    264: };
                    265: 
1.1.1.2 ! root      266: static int nsyscalls = ARRAY_SIZE(scnames);
1.1       root      267: 
                    268: /*
                    269:  * The public interface to this module.
                    270:  */
                    271: void
                    272: print_syscall(int num,
                    273:               abi_long arg1, abi_long arg2, abi_long arg3,
                    274:               abi_long arg4, abi_long arg5, abi_long arg6)
                    275: {
                    276:     int i;
1.1.1.2 ! root      277:     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 ")";
1.1       root      278: 
                    279:     gemu_log("%d ", getpid() );
                    280: 
                    281:     for(i=0;i<nsyscalls;i++)
                    282:         if( scnames[i].nr == num ) {
                    283:             if( scnames[i].call != NULL ) {
                    284:                 scnames[i].call(&scnames[i],arg1,arg2,arg3,arg4,arg5,arg6);
                    285:             } else {
                    286:                 /* XXX: this format system is broken because it uses
                    287:                    host types and host pointers for strings */
                    288:                 if( scnames[i].format != NULL )
                    289:                     format = scnames[i].format;
                    290:                 gemu_log(format,scnames[i].name, arg1,arg2,arg3,arg4,arg5,arg6);
                    291:             }
1.1.1.2 ! root      292:             return;
1.1       root      293:         }
1.1.1.2 ! root      294:     gemu_log("Unknown syscall %d\n", num);
1.1       root      295: }
                    296: 
                    297: 
                    298: void
                    299: print_syscall_ret(int num, abi_long ret)
                    300: {
                    301:     int i;
                    302: 
                    303:     for(i=0;i<nsyscalls;i++)
                    304:         if( scnames[i].nr == num ) {
                    305:             if( scnames[i].result != NULL ) {
                    306:                 scnames[i].result(&scnames[i],ret);
                    307:             } else {
                    308:                 if( ret < 0 ) {
                    309:                     gemu_log(" = -1 errno=" TARGET_ABI_FMT_ld " (%s)\n", -ret, target_strerror(-ret));
                    310:                 } else {
                    311:                     gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret);
                    312:                 }
                    313:             }
                    314:             break;
                    315:         }
                    316: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.