Skip to content

Commit c84be71

Browse files
bozutafvivier
authored andcommitted
linux-user: Extend strace support to enable argument printing after syscall execution
Structure "struct syscallname" in file "strace.c" is used for "-strace" to print arguments and return values of syscalls. The last field of this structure "result" represents the calling function that prints the return values. This field was extended in this patch so that this function takes all syscalls arguments beside the return value. In this way, it enables "-strace" to print arguments of syscalls that have changed after the syscall execution. This extension will be useful as there are many syscalls that return values inside their arguments (i.e. listxattr() that returns the list of extended attributes inside the "list" argument). Implementation notes: Since there are already three existing "print_syscall_ret*" functions inside "strace.c" ("print_syscall_ret_addr()", "print_syscall_ret_adjtimex()", "print_syscall_ret_newselect()"), they were changed to have all syscall arguments beside the return value. This was done so that these functions don't cause build errors (even though syscall arguments are not used in these functions). There is code repetition in these functions for checking the return value and printing the approppriate error message (this code is also located in print_syscall_ret() at the end of "strace.c"). That is the reason why a function "syscall_print_err()" was added for this code and put inside these functions. Functions "print_newselect()" and "print_syscall_ret_newselect()" were changed to use this new implemented functionality and not store the syscall argument values in separate static variables. Signed-off-by: Filip Bozuta <[email protected]> Reviewed-by: Laurent Vivier <[email protected]> Message-Id: <[email protected]> Signed-off-by: Laurent Vivier <[email protected]>
1 parent e865b97 commit c84be71

File tree

3 files changed

+61
-55
lines changed

3 files changed

+61
-55
lines changed

linux-user/qemu.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,9 @@ int host_to_target_waitstatus(int status);
383383
void print_syscall(int num,
384384
abi_long arg1, abi_long arg2, abi_long arg3,
385385
abi_long arg4, abi_long arg5, abi_long arg6);
386-
void print_syscall_ret(int num, abi_long arg1);
386+
void print_syscall_ret(int num, abi_long ret,
387+
abi_long arg1, abi_long arg2, abi_long arg3,
388+
abi_long arg4, abi_long arg5, abi_long arg6);
387389
/**
388390
* print_taken_signal:
389391
* @target_signum: target signal being taken

linux-user/strace.c

Lines changed: 57 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ struct syscallname {
1919
void (*call)(const struct syscallname *,
2020
abi_long, abi_long, abi_long,
2121
abi_long, abi_long, abi_long);
22-
void (*result)(const struct syscallname *, abi_long);
22+
void (*result)(const struct syscallname *, abi_long,
23+
abi_long, abi_long, abi_long,
24+
abi_long, abi_long, abi_long);
2325
};
2426

2527
#ifdef __GNUC__
@@ -631,33 +633,20 @@ print_clockid(int clockid, int last)
631633

632634
/* select */
633635
#ifdef TARGET_NR__newselect
634-
static long newselect_arg1 = 0;
635-
static long newselect_arg2 = 0;
636-
static long newselect_arg3 = 0;
637-
static long newselect_arg4 = 0;
638-
static long newselect_arg5 = 0;
639-
640636
static void
641637
print_newselect(const struct syscallname *name,
642638
abi_long arg1, abi_long arg2, abi_long arg3,
643639
abi_long arg4, abi_long arg5, abi_long arg6)
644640
{
645-
qemu_log("%s(" TARGET_ABI_FMT_ld ",", name->name, arg1);
641+
print_syscall_prologue(name);
646642
print_fdset(arg1, arg2);
647643
qemu_log(",");
648644
print_fdset(arg1, arg3);
649645
qemu_log(",");
650646
print_fdset(arg1, arg4);
651647
qemu_log(",");
652648
print_timeval(arg5, 1);
653-
qemu_log(")");
654-
655-
/* save for use in the return output function below */
656-
newselect_arg1=arg1;
657-
newselect_arg2=arg2;
658-
newselect_arg3=arg3;
659-
newselect_arg4=arg4;
660-
newselect_arg5=arg5;
649+
print_syscall_epilogue(name);
661650
}
662651
#endif
663652

@@ -736,17 +725,29 @@ print_ipc(const struct syscallname *name,
736725
*/
737726

738727
static void
739-
print_syscall_ret_addr(const struct syscallname *name, abi_long ret)
728+
print_syscall_err(abi_long ret)
740729
{
741730
const char *errstr = NULL;
742731

732+
qemu_log(" = ");
743733
if (ret < 0) {
734+
qemu_log("-1 errno=%d", errno);
744735
errstr = target_strerror(-ret);
736+
if (errstr) {
737+
qemu_log(" (%s)", errstr);
738+
}
745739
}
746-
if (errstr) {
747-
qemu_log(" = -1 errno=%d (%s)\n", (int)-ret, errstr);
748-
} else {
749-
qemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret);
740+
}
741+
742+
static void
743+
print_syscall_ret_addr(const struct syscallname *name, abi_long ret,
744+
abi_long arg0, abi_long arg1, abi_long arg2,
745+
abi_long arg3, abi_long arg4, abi_long arg5)
746+
{
747+
print_syscall_err(ret);
748+
749+
if (ret >= 0) {
750+
qemu_log("0x" TARGET_ABI_FMT_lx "\n", ret);
750751
}
751752
}
752753

@@ -760,17 +761,25 @@ print_syscall_ret_raw(struct syscallname *name, abi_long ret)
760761

761762
#ifdef TARGET_NR__newselect
762763
static void
763-
print_syscall_ret_newselect(const struct syscallname *name, abi_long ret)
764-
{
765-
qemu_log(" = 0x" TARGET_ABI_FMT_lx " (", ret);
766-
print_fdset(newselect_arg1,newselect_arg2);
767-
qemu_log(",");
768-
print_fdset(newselect_arg1,newselect_arg3);
769-
qemu_log(",");
770-
print_fdset(newselect_arg1,newselect_arg4);
771-
qemu_log(",");
772-
print_timeval(newselect_arg5, 1);
773-
qemu_log(")\n");
764+
print_syscall_ret_newselect(const struct syscallname *name, abi_long ret,
765+
abi_long arg0, abi_long arg1, abi_long arg2,
766+
abi_long arg3, abi_long arg4, abi_long arg5)
767+
{
768+
print_syscall_err(ret);
769+
770+
if (ret >= 0) {
771+
qemu_log(" = 0x" TARGET_ABI_FMT_lx " (", ret);
772+
print_fdset(arg0, arg1);
773+
qemu_log(",");
774+
print_fdset(arg0, arg2);
775+
qemu_log(",");
776+
print_fdset(arg0, arg3);
777+
qemu_log(",");
778+
print_timeval(arg4, 1);
779+
qemu_log(")");
780+
}
781+
782+
qemu_log("\n");
774783
}
775784
#endif
776785

@@ -783,18 +792,13 @@ print_syscall_ret_newselect(const struct syscallname *name, abi_long ret)
783792
#define TARGET_TIME_ERROR 5 /* clock not synchronized */
784793
#ifdef TARGET_NR_adjtimex
785794
static void
786-
print_syscall_ret_adjtimex(const struct syscallname *name, abi_long ret)
795+
print_syscall_ret_adjtimex(const struct syscallname *name, abi_long ret,
796+
abi_long arg0, abi_long arg1, abi_long arg2,
797+
abi_long arg3, abi_long arg4, abi_long arg5)
787798
{
788-
const char *errstr = NULL;
799+
print_syscall_err(ret);
789800

790-
qemu_log(" = ");
791-
if (ret < 0) {
792-
qemu_log("-1 errno=%d", errno);
793-
errstr = target_strerror(-ret);
794-
if (errstr) {
795-
qemu_log(" (%s)", errstr);
796-
}
797-
} else {
801+
if (ret >= 0) {
798802
qemu_log(TARGET_ABI_FMT_ld, ret);
799803
switch (ret) {
800804
case TARGET_TIME_OK:
@@ -2847,25 +2851,25 @@ print_syscall(int num,
28472851

28482852

28492853
void
2850-
print_syscall_ret(int num, abi_long ret)
2854+
print_syscall_ret(int num, abi_long ret,
2855+
abi_long arg1, abi_long arg2, abi_long arg3,
2856+
abi_long arg4, abi_long arg5, abi_long arg6)
28512857
{
28522858
int i;
2853-
const char *errstr = NULL;
28542859

28552860
for(i=0;i<nsyscalls;i++)
28562861
if( scnames[i].nr == num ) {
28572862
if( scnames[i].result != NULL ) {
2858-
scnames[i].result(&scnames[i], ret);
2863+
scnames[i].result(&scnames[i], ret,
2864+
arg1, arg2, arg3,
2865+
arg4, arg5, arg6);
28592866
} else {
2860-
if (ret < 0) {
2861-
errstr = target_strerror(-ret);
2862-
}
2863-
if (errstr) {
2864-
qemu_log(" = -1 errno=" TARGET_ABI_FMT_ld " (%s)\n",
2865-
-ret, errstr);
2866-
} else {
2867-
qemu_log(" = " TARGET_ABI_FMT_ld "\n", ret);
2867+
print_syscall_err(ret);
2868+
2869+
if (ret >= 0) {
2870+
qemu_log(TARGET_ABI_FMT_ld, ret);
28682871
}
2872+
qemu_log("\n");
28692873
}
28702874
break;
28712875
}

linux-user/syscall.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12565,7 +12565,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
1256512565
arg5, arg6, arg7, arg8);
1256612566

1256712567
if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {
12568-
print_syscall_ret(num, ret);
12568+
print_syscall_ret(num, ret, arg1, arg2, arg3, arg4, arg5, arg6);
1256912569
}
1257012570

1257112571
record_syscall_return(cpu, num, ret);

0 commit comments

Comments
 (0)