trace.c revision f1bfe203f5f1c0e11a614f9d593a68406f5cb47e
1#if HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#include <sys/types.h>
6#include <sys/wait.h>
7#include <signal.h>
8#include <sys/ptrace.h>
9#include <asm/ptrace.h>
10
11#include "ltrace.h"
12
13#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
14# define PTRACE_PEEKUSER PTRACE_PEEKUSR
15#endif
16
17#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
18# define PTRACE_POKEUSER PTRACE_POKEUSR
19#endif
20
21/* Returns 1 if syscall, 2 if sysret, 0 otherwise.
22 */
23#define SYSCALL_INSN   0x44000002
24int
25syscall_p(struct process * proc, int status, int * sysnum) {
26	if (WIFSTOPPED(status) && WSTOPSIG(status)==SIGTRAP) {
27		int pc = ptrace(PTRACE_PEEKUSER, proc->pid, 4*PT_NIP, 0);
28		int insn = ptrace(PTRACE_PEEKTEXT, proc->pid, pc-4, 0);
29
30		if (insn == SYSCALL_INSN) {
31			*sysnum = ptrace(PTRACE_PEEKUSER, proc->pid, 4*PT_RO, 0);
32			if (proc->callstack_depth > 0 &&
33					proc->callstack[proc->callstack_depth-1].is_syscall) {
34				return 2;
35			}
36			if (*sysnum >= 0 && *sysnum <= 255) {
37				return 1;
38			}
39		}
40	}
41	return 0;
42}
43
44long
45gimme_arg(enum tof type, struct process * proc, int arg_num) {
46	if (arg_num==-1) {		/* return value */
47		return ptrace(PTRACE_PEEKUSER, proc->pid, 4*PT_R3, 0);
48	}
49
50	if (type==LT_TOF_FUNCTION || type==LT_TOF_SYSCALL) {
51		if (arg_num < 8) {
52			return ptrace(PTRACE_PEEKUSER, proc->pid, 4*(arg_num+PT_R3), 0);
53		} else {
54			return ptrace(PTRACE_PEEKDATA, proc->pid, proc->stack_pointer+4*(arg_num-8), 0); /* Check */
55		}
56	} else {
57		fprintf(stderr, "gimme_arg called with wrong arguments\n");
58		exit(1);
59	}
60	return 0;
61}
62