trace.c revision 2d45b1a8e26a36a9f85dc49e721c4390ca93dc40
1#if HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#include <stdlib.h>
6#include <sys/types.h>
7#include <sys/wait.h>
8#include <signal.h>
9#include <string.h>
10#include "ptrace.h"
11#include "ltrace.h"
12
13extern FILE *output;
14extern int opt_d;
15
16void get_arch_dep(struct process *proc)
17{
18	proc_archdep *a;
19	if (!proc->arch_ptr)
20		proc->arch_ptr = (void *)malloc(sizeof(proc_archdep));
21	a = (proc_archdep *) (proc->arch_ptr);
22	a->valid = (ptrace(PTRACE_GETREGS, proc->pid, &a->regs, 0) >= 0);
23}
24
25/* Returns syscall number if `pid' stopped because of a syscall.
26 * Returns -1 otherwise
27 */
28int syscall_p(struct process *proc, int status, int *sysnum)
29{
30	if (WIFSTOPPED(status)
31	    && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) {
32		void *ip = get_instruction_pointer(proc);
33		unsigned int insn;
34		if (ip == (void *)-1)
35			return 0;
36		insn = ptrace(PTRACE_PEEKTEXT, proc->pid, ip, 0);
37		if ((insn & 0xc1f8007f) == 0x81d00010) {
38			*sysnum = ((proc_archdep *) proc->arch_ptr)->regs.r_g1;
39			if ((proc->callstack_depth > 0)
40			    && proc->callstack[proc->callstack_depth -
41					       1].is_syscall) {
42				return 2;
43			} else if (*sysnum >= 0) {
44				return 1;
45			}
46		}
47	}
48	return 0;
49}
50
51long gimme_arg(enum tof type, struct process *proc, int arg_num)
52{
53	proc_archdep *a = (proc_archdep *) proc->arch_ptr;
54	if (!a->valid) {
55		fprintf(stderr, "Could not get child registers\n");
56		exit(1);
57	}
58	if (arg_num == -1)	/* return value */
59		return a->regs.r_o0;
60
61	if (type == LT_TOF_FUNCTION || type == LT_TOF_SYSCALL || arg_num >= 6) {
62		if (arg_num < 6)
63			return ((int *)&a->regs.r_o0)[arg_num];
64		return ptrace(PTRACE_PEEKTEXT, proc->pid,
65			      proc->stack_pointer + 64 * (arg_num + 1));
66	} else if (type == LT_TOF_FUNCTIONR)
67		return a->func_arg[arg_num];
68	else if (type == LT_TOF_SYSCALLR)
69		return a->sysc_arg[arg_num];
70	else {
71		fprintf(stderr, "gimme_arg called with wrong arguments\n");
72		exit(1);
73	}
74	return 0;
75}
76
77void save_register_args(enum tof type, struct process *proc)
78{
79	proc_archdep *a = (proc_archdep *) proc->arch_ptr;
80	if (a->valid) {
81		if (type == LT_TOF_FUNCTION)
82			memcpy(a->func_arg, &a->regs.r_o0, sizeof(a->func_arg));
83		else
84			memcpy(a->sysc_arg, &a->regs.r_o0, sizeof(a->sysc_arg));
85	}
86}
87