trace.c revision b1dd77d66f93eeaa6cbf8b101d3e9cf70981e000
1/*
2** S390 specific part of trace.c
3**
4** Other routines are in ../trace.c and need to be combined
5** at link time with this code.
6**
7** S/390 version
8** (C) Copyright 2001 IBM Poughkeepsie, IBM Corporation
9*/
10
11#if HAVE_CONFIG_H
12#include "config.h"
13#endif
14
15#include <sys/types.h>
16#include <sys/wait.h>
17#include <signal.h>
18#include <sys/ptrace.h>
19#include <asm/ptrace.h>
20
21#include "ltrace.h"
22
23#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
24# define PTRACE_PEEKUSER PTRACE_PEEKUSR
25#endif
26
27#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
28# define PTRACE_POKEUSER PTRACE_POKEUSR
29#endif
30
31/* Returns 1 if syscall, 2 if sysret, 0 otherwise.
32 */
33int
34syscall_p(struct process * proc, int status, int * sysnum) {
35	long pswa;
36	long svcinst;
37	long svcno;
38	long svcop;
39
40	if (WIFSTOPPED(status) && WSTOPSIG(status)==SIGTRAP) {
41
42		pswa = ptrace(PTRACE_PEEKUSER, proc->pid, PT_PSWADDR, 0);
43		svcinst = ptrace(PTRACE_PEEKTEXT, proc->pid, (char *)(pswa-4),0);
44		svcop = (svcinst >> 8) & 0xFF;
45		svcno = svcinst & 0xFF;
46
47		*sysnum = svcno;
48
49		if (*sysnum == -1) {
50			return 0;
51		}
52		if (svcop == 0 && svcno == 1) {
53			/* Breakpoint was hit... */
54			return 0;
55		}
56		if (svcop == 10 && *sysnum>=0) {
57			/* System call was encountered... */
58			if (proc->current_syscall!=*sysnum) {
59				return 1;
60			} else {
61				return 2;
62			}
63		}
64		else {
65			/* Unknown trap was encountered... */
66			return 0;
67		}
68	}
69	/* Unknown status... */
70	return 0;
71}
72
73void
74continue_after_breakpoint(struct process *proc, struct breakpoint * sbp) {
75	if (sbp->enabled) disable_breakpoint(proc->pid, sbp);
76	ptrace(PTRACE_POKEUSER, proc->pid, PT_PSWADDR, sbp->addr);
77	if (sbp->enabled == 0) {
78		continue_process(proc->pid);
79	} else {
80		proc->breakpoint_being_enabled = sbp;
81		ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0);
82	}
83}
84
85long
86gimme_arg(enum tof type, struct process * proc, int arg_num) {
87	if (arg_num==-1) {		/* return value */
88		return ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR2, 0);
89	}
90
91	if (type==LT_TOF_FUNCTION) {
92		switch(arg_num) {
93			case 0: return ptrace(PTRACE_PEEKUSER, proc->pid, PT_ORIGGPR2, 0);
94			case 1: return ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR3, 0);
95			case 2: return ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR4, 0);
96			case 3: return ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR5, 0);
97			case 4: return ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR6, 0);
98			default:
99					fprintf(stderr, "gimme_arg called with wrong arguments\n");
100					exit(2);
101		}
102
103	} else if (type==LT_TOF_SYSCALL) {
104		switch(arg_num) {
105			case 0: return ptrace(PTRACE_PEEKUSER, proc->pid, PT_ORIGGPR2, 0);
106			case 1: return ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR3, 0);
107			case 2: return ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR4, 0);
108			case 3: return ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR5, 0);
109			case 4: return ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR6, 0);
110			default:
111				fprintf(stderr, "gimme_arg called with wrong arguments\n");
112				exit(2);
113		}
114	} else {
115		fprintf(stderr, "gimme_arg called with wrong arguments\n");
116		exit(1);
117	}
118
119	return 0;
120}
121