-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add new files fir strace support, missed in earlier commit.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3504 c046a42c-6fe2-441c-8c8c-71466251a162
- Loading branch information
ths
committed
Nov 1, 2007
1 parent
93a0019
commit 33189d3
Showing
2 changed files
with
1,814 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,299 @@ | ||
#include <stdio.h> | ||
#include <errno.h> | ||
#include <sys/ipc.h> | ||
#include <sys/msg.h> | ||
#include <sys/sem.h> | ||
#include <sys/shm.h> | ||
#include <sys/select.h> | ||
#include <sys/types.h> | ||
#include <unistd.h> | ||
#include "qemu.h" | ||
|
||
int do_strace=0; | ||
|
||
struct syscallname { | ||
int nr; | ||
char *name; | ||
char *format; | ||
void (*call)(struct syscallname *, | ||
target_long, target_long, target_long, | ||
target_long, target_long, target_long); | ||
void (*result)(struct syscallname *, target_long); | ||
}; | ||
|
||
/* | ||
* 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_fdset(int n, target_ulong target_fds_addr) | ||
{ | ||
int i; | ||
|
||
gemu_log("["); | ||
if( target_fds_addr ) { | ||
target_long *target_fds; | ||
|
||
if (!access_ok(VERIFY_READ, target_fds_addr, sizeof(*target_fds)*(n / TARGET_LONG_BITS + 1))) | ||
return; | ||
|
||
target_fds = lock_user(target_fds_addr, sizeof(*target_fds)*(n / TARGET_LONG_BITS + 1), 1); | ||
for (i=n; i>=0; i--) { | ||
if ((tswapl(target_fds[i / TARGET_LONG_BITS]) >> (i & (TARGET_LONG_BITS - 1))) & 1) | ||
gemu_log("%d,", i ); | ||
} | ||
unlock_user(target_fds, target_fds_addr, 0); | ||
} | ||
gemu_log("]"); | ||
} | ||
|
||
static void | ||
print_timeval(target_ulong tv_addr) | ||
{ | ||
if( tv_addr ) { | ||
struct target_timeval *tv; | ||
|
||
if (!access_ok(VERIFY_READ, tv_addr, sizeof(*tv))) | ||
return; | ||
|
||
tv = lock_user(tv_addr, sizeof(*tv), 1); | ||
gemu_log("{%d,%d}", tv->tv_sec, tv->tv_usec); | ||
unlock_user(tv, tv_addr, 0); | ||
} else | ||
gemu_log("NULL"); | ||
} | ||
|
||
/* | ||
* Sysycall specific output functions | ||
*/ | ||
|
||
/* select */ | ||
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(struct syscallname *name, | ||
target_long arg1, target_long arg2, target_long arg3, | ||
target_long arg4, target_long arg5, target_long arg6) | ||
{ | ||
gemu_log("%s(" TARGET_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); | ||
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; | ||
} | ||
|
||
static void | ||
print_semctl(struct syscallname *name, | ||
target_long arg1, target_long arg2, target_long arg3, | ||
target_long arg4, target_long arg5, target_long arg6) | ||
{ | ||
gemu_log("%s(" TARGET_FMT_ld "," TARGET_FMT_ld ",", name->name, arg1, arg2); | ||
print_ipc_cmd(arg3); | ||
gemu_log(",0x" TARGET_FMT_lx ")", arg4); | ||
} | ||
|
||
static void | ||
print_execve(struct syscallname *name, | ||
target_long arg1, target_long arg2, target_long arg3, | ||
target_long arg4, target_long arg5, target_long arg6) | ||
{ | ||
target_ulong arg_ptr_addr; | ||
char *s; | ||
|
||
if (!access_ok(VERIFY_READ, arg1, 1)) | ||
return; | ||
|
||
s = lock_user_string(arg1); | ||
gemu_log("%s(\"%s\",{", name->name, s); | ||
unlock_user(s, arg1, 0); | ||
|
||
for (arg_ptr_addr = arg2; ; arg_ptr_addr += sizeof(target_ulong)) { | ||
target_ulong *arg_ptr, arg_addr, s_addr; | ||
|
||
if (!access_ok(VERIFY_READ, arg_ptr_addr, sizeof(target_ulong))) | ||
return; | ||
|
||
arg_ptr = lock_user(arg_ptr_addr, sizeof(target_ulong), 1); | ||
arg_addr = tswapl(*arg_ptr); | ||
unlock_user(arg_ptr, arg_ptr_addr, 0); | ||
if (!arg_addr) | ||
break; | ||
s = lock_user_string(arg_addr); | ||
gemu_log("\"%s\",", s); | ||
unlock_user(s, s_addr, 0); | ||
} | ||
|
||
gemu_log("NULL})"); | ||
} | ||
|
||
static void | ||
print_ipc(struct syscallname *name, | ||
target_long arg1, target_long arg2, target_long arg3, | ||
target_long arg4, target_long arg5, target_long arg6) | ||
{ | ||
switch(arg1) { | ||
case IPCOP_semctl: | ||
name->name = "semctl"; | ||
print_semctl(name,arg2,arg3,arg4,arg5,arg6,0); | ||
break; | ||
default: | ||
gemu_log("%s(" TARGET_FMT_ld "," TARGET_FMT_ld "," TARGET_FMT_ld "," TARGET_FMT_ld ")", | ||
name->name, arg1, arg2, arg3, arg4); | ||
} | ||
} | ||
|
||
/* | ||
* Variants for the return value output function | ||
*/ | ||
|
||
static void | ||
print_syscall_ret_addr(struct syscallname *name, target_long ret) | ||
{ | ||
if( ret == -1 ) { | ||
gemu_log(" = -1 errno=%d (%s)\n", errno, target_strerror(errno)); | ||
} else { | ||
gemu_log(" = " TARGET_FMT_lx "\n", ret); | ||
} | ||
} | ||
|
||
static void | ||
print_syscall_ret_raw(struct syscallname *name, target_long ret) | ||
{ | ||
gemu_log(" = " TARGET_FMT_lx "\n", ret); | ||
} | ||
|
||
static void | ||
print_syscall_ret_newselect(struct syscallname *name, target_long ret) | ||
{ | ||
gemu_log(" = " TARGET_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); | ||
gemu_log(")\n"); | ||
} | ||
|
||
/* | ||
* An array of all of the syscalls we know about | ||
*/ | ||
|
||
static struct syscallname scnames[] = { | ||
#include "strace.list" | ||
}; | ||
|
||
static int nsyscalls = sizeof(scnames)/sizeof(struct syscallname); | ||
|
||
/* | ||
* The public interface to this module. | ||
*/ | ||
void | ||
print_syscall(int num, | ||
target_long arg1, target_long arg2, target_long arg3, | ||
target_long arg4, target_long arg5, target_long arg6) | ||
{ | ||
int i; | ||
char *format="%s(%ld,%ld,%ld,%ld,%ld,%ld)"; | ||
|
||
gemu_log("%d ", getpid() ); | ||
|
||
for(i=0;i<nsyscalls;i++) | ||
if( scnames[i].nr == num ) { | ||
if( scnames[i].call != NULL ) { | ||
scnames[i].call(&scnames[i],arg1,arg2,arg3,arg4,arg5,arg6); | ||
} else { | ||
if( scnames[i].format != NULL ) | ||
format = scnames[i].format; | ||
gemu_log(format,scnames[i].name, arg1,arg2,arg3,arg4,arg5,arg6); | ||
} | ||
break; | ||
} | ||
} | ||
|
||
|
||
void | ||
print_syscall_ret(int num, target_long ret) | ||
{ | ||
int i; | ||
|
||
for(i=0;i<nsyscalls;i++) | ||
if( scnames[i].nr == num ) { | ||
if( scnames[i].result != NULL ) { | ||
scnames[i].result(&scnames[i],ret); | ||
} else { | ||
if( ret < 0 ) { | ||
gemu_log(" = -1 errno=%d (%s)\n", -ret, target_strerror(-ret)); | ||
} else { | ||
gemu_log(" = %d\n", ret); | ||
} | ||
} | ||
break; | ||
} | ||
} | ||
|
Oops, something went wrong.